<commit_before>#include "geometry/triangular_mesh.h"
#include "const.h"
#include <cassert>

namespace hd {
  TriangularMesh::TriangularMesh() {
    _vertices.clear();
    _edges.clear();
    _faces.clear();
    _isPopulated = false;
    _vertexNormalMode = TriangularMesh::VertexNormalMode::AVERAGED;
    _faceNormalMode = TriangularMesh::FaceNormalMode::FLAT;
  }

  TriangularMesh::TriangularMesh(const TriangularMesh& mesh) {
    _vertices.insert(_vertices.end(), mesh._vertices.begin(), mesh._vertices.end());
    _edges.insert(_edges.end(), mesh._edges.begin(), mesh._edges.end());
    _faces.insert(_faces.end(), mesh._faces.begin(), mesh._faces.end());
    _isPopulated = mesh._isPopulated;
    _boundingBox = mesh._boundingBox;
    _vertexNormalMode = mesh._vertexNormalMode;
    _faceNormalMode = mesh._faceNormalMode;
  }

  TriangularMesh::~TriangularMesh() {
    _vertices.clear();
    _edges.clear();
    _faces.clear();
  }

  TriangularMesh::Builder TriangularMesh::newBuilder(
      TriangularMesh::VertexNormalMode vertexNormalMode,
      TriangularMesh::FaceNormalMode faceNormalMode) {
    return TriangularMesh::Builder(vertexNormalMode, faceNormalMode);
  }

  TriangularMesh::Vertex TriangularMesh::v(unsigned int index) const {
    assert(index <  vertexNum());
    return _vertices[index];
  }

  TriangularMesh::Face TriangularMesh::f(unsigned int index) const {
    assert(index < faceNum());
    return _faces[index];
  }

  TriangularMesh::Edge TriangularMesh::e(unsigned int index) const {
    assert(index < edgeNum());
    return _edges[index];
  }

  unsigned int TriangularMesh::vertexNum() const {
    return _vertices.size();
  }

  unsigned int TriangularMesh::edgeNum() const {
    return _edges.size();
  }

  unsigned int TriangularMesh::faceNum() const {
    return _faces.size();
  }

  Triangle3 TriangularMesh::triangle(unsigned int index) const {
    assert(isPopulated());
    assert(index < faceNum());
    auto f = _faces[index];
    auto faceVertices = std::array<Vector3, 3>();
    for (int vInd = 0; vInd < 3; ++vInd) {
      faceVertices[vInd] = v(f.vertices[vInd]).pos;
    }
    return Triangle3(faceVertices);
  }

  Vector3 TriangularMesh::normal(const TriangularMesh::MeshPoint& p) const {
    assert(isPopulated());
    assert(p.faceId < faceNum());
    if (_faceNormalMode != TriangularMesh::FaceNormalMode::PHONG) {
      return f(p.faceId).normal;
    }
    Vector3 avgNormal = Vector3::zero();
    for (unsigned int i = 0; i < 3; ++i) {
      avgNormal += p.params[i] * v(f(p.faceId).vertices[i]).pos;
    }
    return avgNormal.normalize();
  }

  BoundingBox3 TriangularMesh::boundingBox3() const {
    assert(isPopulated());
    return _boundingBox;
  }

  void TriangularMesh::populate() {
    assert(!isPopulated());
    _populateEdges();
    _populateNormals();
    _populateBoundingBox();
    _isPopulated = true;
  }

  void TriangularMesh::_populateEdges() {
    // Generate all edges. Update edge lists of vertices and faces.
    _edges.resize(_faces.size() * 3);
    for (unsigned int fid = 0; fid < _faces.size(); ++fid) {
      auto face = _faces[fid];
      for (unsigned int eid = 0; eid < 3; ++eid) {
        unsigned int edgeId = fid * 3 + eid;
        TriangularMesh::Edge edge = TriangularMesh::Edge();
        edge.startVertex = face.vertices[eid];
        edge.endVertex = face.vertices[(eid + 1) % 3];
        edge.face = fid;
        edge.nextEdge = fid * 3 + (eid + 1) % 3;
        // prev edge should be (eid - 1) % 3. To avoid overflow when eid is 0, we instead
        // use (eid + 2) % 3.
        edge.prevEdge = fid * 3 + (eid + 2) % 3;
        _edges[edgeId] = edge;
        _faces[fid].edges[eid] = edgeId;
        _vertices[edge.startVertex].edges.push_back(edgeId);
      }
    }
    // Rescan all edges, and populate twin edges.
    for (unsigned int eid = 0; eid < _edges.size(); ++eid) {
      unsigned int startVertex = _edges[eid].startVertex;
      unsigned int endVertex = _edges[eid].endVertex;
      for (unsigned int revEdgeId : _vertices[endVertex].edges) {
        if (_edges[revEdgeId].endVertex == startVertex) {
          _edges[eid].twinEdge = revEdgeId;
          break;
        }
        _edges[eid].twinEdge = HD_INVALID_ID;
      }
    }
  }

  void TriangularMesh::_populateNormals() {
    if (_faceNormalMode != TriangularMesh::FaceNormalMode::USER_SPECIFIED) {
      // Calculate natual normals if face normal mdoe is not user-specified. Although this will
      // not be used for Phong interpolation mode, it is still reqired as an intermeidate step
      // to calculate averaged vertex normals.
      for (unsigned int fid = 0; fid < faceNum(); ++fid) {
        auto f = _faces[fid];
        Vector3 e0 = v(f.vertices[1]).pos - v(f.vertices[0]).pos;
        Vector3 e1 = v(f.vertices[2]).pos - v(f.vertices[1]).pos;
        Vector3 n = e0 ^ e1;
        assert(n.len2() > HD_EPSILON_TINY);
        _faces[fid].normal = n.normalize();
      }
    }
    if (_vertexNormalMode != TriangularMesh::VertexNormalMode::USER_SPECIFIED) {
      for (unsigned int vid = 0; vid < vertexNum(); ++vid) {
        Vector3 sumOfFaceNormals = Vector3::zero();
        // Vertex does not directly store all of its adjacent faces. Instead, we go through
        // every edge starts from it, whose belonging faces must be adjacent to this vertex.
        for (unsigned int eid : v(vid).edges) {
          sumOfFaceNormals += f(e(eid).face).normal;
        }
        // We don't need to devide sum vector by number of edges: normalization will just include
        // this procedure.
        _vertices[vid].normal = sumOfFaceNormals.normalize();
      }
    }
  }

  void TriangularMesh::_populateBoundingBox() {
    Vector3 minBound = Vector3::identity(HD_INFINITY);
    Vector3 maxBound = Vector3::identity(-HD_INFINITY);
    for (auto v : _vertices) {
      for (unsigned int i = 0; i < 3; ++i) {
        if (v.pos[i] < minBound[i]) {
          minBound[i] = v.pos[i];
        }
        if (v.pos[i] > maxBound[i]) {
          maxBound[i] = v.pos[i];
        }
      }
    }
    _boundingBox = BoundingBox3(minBound, maxBound);
  }

  bool TriangularMesh::isPopulated() const {
    return _isPopulated;
  }

  TriangularMesh::VertexNormalMode TriangularMesh::vertexNormalMode() const {
    return _vertexNormalMode;
  }

  TriangularMesh::FaceNormalMode TriangularMesh::faceNormalMode() const {
    return _faceNormalMode;
  }

  TriangularMesh::Builder::Builder(
      TriangularMesh::VertexNormalMode vertexNormalMode,
      TriangularMesh::FaceNormalMode faceNormalMode) {
    _instance = std::unique_ptr<TriangularMesh>(new TriangularMesh());
    _instance->_vertexNormalMode = vertexNormalMode;
    _instance->_faceNormalMode = faceNormalMode;
  }

  TriangularMesh::Builder& TriangularMesh::Builder::addVertex(const Vector3& v) {
    assert(_instance->vertexNormalMode() != TriangularMesh::VertexNormalMode::USER_SPECIFIED);
    assert(!_instance->isPopulated());
    _instance->_vertices.push_back(TriangularMesh::Vertex(v));
    return *this;
  }

  TriangularMesh::Builder& TriangularMesh::Builder::addVertex(
      const Vector3& v, const Vector3& vn) {
    assert(_instance->vertexNormalMode() == TriangularMesh::VertexNormalMode::USER_SPECIFIED);
    assert(!_instance->isPopulated());
    _instance->_vertices.push_back(TriangularMesh::Vertex(v, vn));
    return *this;
  }

  TriangularMesh::Builder& TriangularMesh::Builder::addFace(
      const std::array<unsigned int, 3>& face) {
    assert(_instance->faceNormalMode() != TriangularMesh::FaceNormalMode::USER_SPECIFIED);
    assert(!_instance->isPopulated());
    _instance->_faces.push_back(TriangularMesh::Face(face));
    return *this;
  }

  TriangularMesh::Builder& TriangularMesh::Builder::addFace(
      const std::array<unsigned int, 3>& face, const Vector3& fn) {
    assert(_instance->faceNormalMode() == TriangularMesh::FaceNormalMode::USER_SPECIFIED);
    assert(!_instance->isPopulated());
    _instance->_faces.push_back(TriangularMesh::Face(face, fn));
    return *this;
  }

  std::unique_ptr<TriangularMesh> TriangularMesh::Builder::build(bool populate) {
    if (populate && !_instance->isPopulated()) {
      _instance->populate();
    }
    auto ptr = std::unique_ptr<TriangularMesh>(_instance.release());
    return ptr;
  }
}
<commit_msg>Fix one more bug calculating bounding box of TriangularMesh.<commit_after>#include "geometry/triangular_mesh.h"
#include "const.h"
#include <cassert>

namespace hd {
  TriangularMesh::TriangularMesh() {
    _vertices.clear();
    _edges.clear();
    _faces.clear();
    _isPopulated = false;
    _vertexNormalMode = TriangularMesh::VertexNormalMode::AVERAGED;
    _faceNormalMode = TriangularMesh::FaceNormalMode::FLAT;
  }

  TriangularMesh::TriangularMesh(const TriangularMesh& mesh) {
    _vertices.insert(_vertices.end(), mesh._vertices.begin(), mesh._vertices.end());
    _edges.insert(_edges.end(), mesh._edges.begin(), mesh._edges.end());
    _faces.insert(_faces.end(), mesh._faces.begin(), mesh._faces.end());
    _isPopulated = mesh._isPopulated;
    _boundingBox = mesh._boundingBox;
    _vertexNormalMode = mesh._vertexNormalMode;
    _faceNormalMode = mesh._faceNormalMode;
  }

  TriangularMesh::~TriangularMesh() {
    _vertices.clear();
    _edges.clear();
    _faces.clear();
  }

  TriangularMesh::Builder TriangularMesh::newBuilder(
      TriangularMesh::VertexNormalMode vertexNormalMode,
      TriangularMesh::FaceNormalMode faceNormalMode) {
    return TriangularMesh::Builder(vertexNormalMode, faceNormalMode);
  }

  TriangularMesh::Vertex TriangularMesh::v(unsigned int index) const {
    assert(index <  vertexNum());
    return _vertices[index];
  }

  TriangularMesh::Face TriangularMesh::f(unsigned int index) const {
    assert(index < faceNum());
    return _faces[index];
  }

  TriangularMesh::Edge TriangularMesh::e(unsigned int index) const {
    assert(index < edgeNum());
    return _edges[index];
  }

  unsigned int TriangularMesh::vertexNum() const {
    return _vertices.size();
  }

  unsigned int TriangularMesh::edgeNum() const {
    return _edges.size();
  }

  unsigned int TriangularMesh::faceNum() const {
    return _faces.size();
  }

  Triangle3 TriangularMesh::triangle(unsigned int index) const {
    assert(isPopulated());
    assert(index < faceNum());
    auto f = _faces[index];
    auto faceVertices = std::array<Vector3, 3>();
    for (int vInd = 0; vInd < 3; ++vInd) {
      faceVertices[vInd] = v(f.vertices[vInd]).pos;
    }
    return Triangle3(faceVertices);
  }

  Vector3 TriangularMesh::normal(const TriangularMesh::MeshPoint& p) const {
    assert(isPopulated());
    assert(p.faceId < faceNum());
    if (_faceNormalMode != TriangularMesh::FaceNormalMode::PHONG) {
      return f(p.faceId).normal;
    }
    Vector3 avgNormal = Vector3::zero();
    for (unsigned int i = 0; i < 3; ++i) {
      avgNormal += p.params[i] * v(f(p.faceId).vertices[i]).pos;
    }
    return avgNormal.normalize();
  }

  BoundingBox3 TriangularMesh::boundingBox3() const {
    assert(isPopulated());
    return _boundingBox;
  }

  void TriangularMesh::populate() {
    assert(!isPopulated());
    _populateEdges();
    _populateNormals();
    _populateBoundingBox();
    _isPopulated = true;
  }

  void TriangularMesh::_populateEdges() {
    // Generate all edges. Update edge lists of vertices and faces.
    _edges.resize(_faces.size() * 3);
    for (unsigned int fid = 0; fid < _faces.size(); ++fid) {
      auto face = _faces[fid];
      for (unsigned int eid = 0; eid < 3; ++eid) {
        unsigned int edgeId = fid * 3 + eid;
        TriangularMesh::Edge edge = TriangularMesh::Edge();
        edge.startVertex = face.vertices[eid];
        edge.endVertex = face.vertices[(eid + 1) % 3];
        edge.face = fid;
        edge.nextEdge = fid * 3 + (eid + 1) % 3;
        // prev edge should be (eid - 1) % 3. To avoid overflow when eid is 0, we instead
        // use (eid + 2) % 3.
        edge.prevEdge = fid * 3 + (eid + 2) % 3;
        _edges[edgeId] = edge;
        _faces[fid].edges[eid] = edgeId;
        _vertices[edge.startVertex].edges.push_back(edgeId);
      }
    }
    // Rescan all edges, and populate twin edges.
    for (unsigned int eid = 0; eid < _edges.size(); ++eid) {
      unsigned int startVertex = _edges[eid].startVertex;
      unsigned int endVertex = _edges[eid].endVertex;
      for (unsigned int revEdgeId : _vertices[endVertex].edges) {
        if (_edges[revEdgeId].endVertex == startVertex) {
          _edges[eid].twinEdge = revEdgeId;
          break;
        }
        _edges[eid].twinEdge = HD_INVALID_ID;
      }
    }
  }

  void TriangularMesh::_populateNormals() {
    if (_faceNormalMode != TriangularMesh::FaceNormalMode::USER_SPECIFIED) {
      // Calculate natual normals if face normal mdoe is not user-specified. Although this will
      // not be used for Phong interpolation mode, it is still reqired as an intermeidate step
      // to calculate averaged vertex normals.
      for (unsigned int fid = 0; fid < faceNum(); ++fid) {
        auto f = _faces[fid];
        Vector3 e0 = v(f.vertices[1]).pos - v(f.vertices[0]).pos;
        Vector3 e1 = v(f.vertices[2]).pos - v(f.vertices[1]).pos;
        Vector3 n = e0 ^ e1;
        assert(n.len2() > HD_EPSILON_TINY);
        _faces[fid].normal = n.normalize();
      }
    }
    if (_vertexNormalMode != TriangularMesh::VertexNormalMode::USER_SPECIFIED) {
      for (unsigned int vid = 0; vid < vertexNum(); ++vid) {
        Vector3 sumOfFaceNormals = Vector3::zero();
        // Vertex does not directly store all of its adjacent faces. Instead, we go through
        // every edge starts from it, whose belonging faces must be adjacent to this vertex.
        for (unsigned int eid : v(vid).edges) {
          sumOfFaceNormals += f(e(eid).face).normal;
        }
        // We don't need to devide sum vector by number of edges: normalization will just include
        // this procedure.
        _vertices[vid].normal = sumOfFaceNormals.normalize();
      }
    }
  }

  void TriangularMesh::_populateBoundingBox() {
    if (_vertices.empty()) {
      _boundingBox = BoundingBox3();
      return;
    }
    Vector3 minBound = Vector3::identity(HD_INFINITY);
    Vector3 maxBound = Vector3::identity(-HD_INFINITY);
    for (auto v : _vertices) {
      for (unsigned int i = 0; i < 3; ++i) {
        if (v.pos[i] < minBound[i]) {
          minBound[i] = v.pos[i];
        }
        if (v.pos[i] > maxBound[i]) {
          maxBound[i] = v.pos[i];
        }
      }
    }
    _boundingBox = BoundingBox3(minBound, maxBound);
  }

  bool TriangularMesh::isPopulated() const {
    return _isPopulated;
  }

  TriangularMesh::VertexNormalMode TriangularMesh::vertexNormalMode() const {
    return _vertexNormalMode;
  }

  TriangularMesh::FaceNormalMode TriangularMesh::faceNormalMode() const {
    return _faceNormalMode;
  }

  TriangularMesh::Builder::Builder(
      TriangularMesh::VertexNormalMode vertexNormalMode,
      TriangularMesh::FaceNormalMode faceNormalMode) {
    _instance = std::unique_ptr<TriangularMesh>(new TriangularMesh());
    _instance->_vertexNormalMode = vertexNormalMode;
    _instance->_faceNormalMode = faceNormalMode;
  }

  TriangularMesh::Builder& TriangularMesh::Builder::addVertex(const Vector3& v) {
    assert(_instance->vertexNormalMode() != TriangularMesh::VertexNormalMode::USER_SPECIFIED);
    assert(!_instance->isPopulated());
    _instance->_vertices.push_back(TriangularMesh::Vertex(v));
    return *this;
  }

  TriangularMesh::Builder& TriangularMesh::Builder::addVertex(
      const Vector3& v, const Vector3& vn) {
    assert(_instance->vertexNormalMode() == TriangularMesh::VertexNormalMode::USER_SPECIFIED);
    assert(!_instance->isPopulated());
    _instance->_vertices.push_back(TriangularMesh::Vertex(v, vn));
    return *this;
  }

  TriangularMesh::Builder& TriangularMesh::Builder::addFace(
      const std::array<unsigned int, 3>& face) {
    assert(_instance->faceNormalMode() != TriangularMesh::FaceNormalMode::USER_SPECIFIED);
    assert(!_instance->isPopulated());
    _instance->_faces.push_back(TriangularMesh::Face(face));
    return *this;
  }

  TriangularMesh::Builder& TriangularMesh::Builder::addFace(
      const std::array<unsigned int, 3>& face, const Vector3& fn) {
    assert(_instance->faceNormalMode() == TriangularMesh::FaceNormalMode::USER_SPECIFIED);
    assert(!_instance->isPopulated());
    _instance->_faces.push_back(TriangularMesh::Face(face, fn));
    return *this;
  }

  std::unique_ptr<TriangularMesh> TriangularMesh::Builder::build(bool populate) {
    if (populate && !_instance->isPopulated()) {
      _instance->populate();
    }
    auto ptr = std::unique_ptr<TriangularMesh>(_instance.release());
    return ptr;
  }
}
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "gccetoolchain.h"
#include "qt4project.h"

#include <utils/qtcassert.h>

#include <QtCore/QDir>
#include <QtCore/QProcess>
#include <QtCore/QtDebug>

enum { debug = 0 };

using namespace ProjectExplorer;
using namespace Qt4ProjectManager::Internal;

// Locate the compiler via path.
static QString gcceCommand(const QString &dir)
{
    ProjectExplorer::Environment env = ProjectExplorer::Environment::systemEnvironment();
    if (!dir.isEmpty()) {
        env.prependOrSetPath(dir + QLatin1String("/bin"));
        env.prependOrSetPath(dir);
    }
    QString gcce = QLatin1String("arm-none-symbianelf-gcc");
#ifdef Q_OS_WIN
    gcce += QLatin1String(".exe");
#endif
    const QString rc = env.searchInPath(gcce);
    if (debug && rc.isEmpty()) {
        const QString msg = QString::fromLatin1("GCCEToolChain: Unable to locate '%1' in '%2' (GCCE root: '%3')")
                            .arg(gcce, env.value(QLatin1String("PATH")), dir);
        qWarning("%s", qPrintable(msg));
        return gcce;
    }
    return rc;
}

// The GccToolChain base class constructor wants to know the gcc command
GCCEToolChain *GCCEToolChain::create(const S60Devices::Device &device,
                                     const QString &gcceRoot,
                                     ProjectExplorer::ToolChain::ToolChainType type)
{
    const QString gccCommand = gcceCommand(gcceRoot);
    const QFileInfo gccCommandFi(gccCommand);
    const QString binPath = gccCommandFi.isRelative() ? QString() : gccCommandFi.absolutePath();
    return new GCCEToolChain(device, binPath, gccCommand, type);
}

GCCEToolChain::GCCEToolChain(const S60Devices::Device &device,
                             const QString &gcceBinPath,
                             const QString &gcceCommand,
                             ProjectExplorer::ToolChain::ToolChainType type) :
    GccToolChain(gcceCommand),
    m_mixin(device),
    m_type(type),
    m_gcceBinPath(gcceBinPath)
{
    QTC_ASSERT(m_type == ProjectExplorer::ToolChain::GCCE || m_type == ProjectExplorer::ToolChain::GCCE_GNUPOC, return)
    if (debug)
        qDebug() << "GCCEToolChain on" << m_type << gcceCommand << gcceBinPath << m_mixin.device();
}

ToolChain::ToolChainType GCCEToolChain::type() const
{
    return m_type;
}

QByteArray GCCEToolChain::predefinedMacros()
{
    if (m_predefinedMacros.isEmpty()) {
        ProjectExplorer::GccToolChain::predefinedMacros();
        m_predefinedMacros += "\n"
                "#define __GCCE__\n"
                "#define __SYMBIAN32__\n";
    }
    return m_predefinedMacros;
}

QList<HeaderPath> GCCEToolChain::systemHeaderPaths()
{
    if (m_systemHeaderPaths.isEmpty()) {
        GccToolChain::systemHeaderPaths();
        switch (m_type) {
        case ProjectExplorer::ToolChain::GCCE:
            m_systemHeaderPaths += m_mixin.epocHeaderPaths();
            break;
        case ProjectExplorer::ToolChain::GCCE_GNUPOC:
            m_systemHeaderPaths += m_mixin.gnuPocHeaderPaths();
            break;
        default:
            break;
        }
    }
    return m_systemHeaderPaths;
}

void GCCEToolChain::addToEnvironment(ProjectExplorer::Environment &env)
{
    if (debug)
        qDebug() << "GCCEToolChain::addToEnvironment" << m_type << gcc() << m_gcceBinPath<< m_mixin.device();

    if (!m_gcceBinPath.isEmpty())
        env.prependOrSetPath(m_gcceBinPath);
    switch (m_type) {
    case ProjectExplorer::ToolChain::GCCE:
        m_mixin.addEpocToEnvironment(&env);
        break;
    case ProjectExplorer::ToolChain::GCCE_GNUPOC:
        m_mixin.addGnuPocToEnvironment(&env);
        break;
    default:
        break;
    }
    QString version = gcceVersion();
    version = version.remove(QLatin1Char('.'));
    env.set(QString::fromLatin1("SBS_GCCE") + version + QLatin1String("BIN"), QDir::toNativeSeparators(m_gcceBinPath));
}

QString GCCEToolChain::makeCommand() const
{
    return QLatin1String("make");
}

bool GCCEToolChain::equals(ToolChain *otherIn) const
{
    if (otherIn->type() != type())
                return false;
    const GCCEToolChain *other = static_cast<const GCCEToolChain *>(otherIn);
    return m_mixin == other->m_mixin
           && m_gcceBinPath == other->m_gcceBinPath
           && gcc() == other->gcc();
}

QString GCCEToolChain::gcceVersion() const
{
    if (m_gcceVersion.isEmpty()) {
        QString command = gcceCommand(m_gcceBinPath);
        if (command.isEmpty())
            return QString();
        QProcess gxx;
        QStringList arguments;
        arguments << QLatin1String("--version");
        ProjectExplorer::Environment env = ProjectExplorer::Environment::systemEnvironment();
        env.set(QLatin1String("LC_ALL"), QLatin1String("C"));   //override current locale settings
        gxx.setEnvironment(env.toStringList());
        gxx.setReadChannelMode(QProcess::MergedChannels);
        gxx.start(command, arguments);
        gxx.closeWriteChannel();
        gxx.waitForFinished();

        QString line;
        if (gxx.canReadLine()) {
            line = gxx.readLine();
            qDebug() << "GCCVersion:" << line;
            QRegExp version("\\s((\\d+)\\.(\\d+)\\.(\\d+))\\s");
            if (line.indexOf(version) >= -1) {
                qDebug() << "    MATCHED!";
                m_gcceVersion = version.cap(1);
            }
        }
    }
    return m_gcceVersion;
}
<commit_msg>Quiten debug messages<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "gccetoolchain.h"
#include "qt4project.h"

#include <utils/qtcassert.h>

#include <QtCore/QDir>
#include <QtCore/QProcess>
#include <QtCore/QtDebug>

enum { debug = 0 };

using namespace ProjectExplorer;
using namespace Qt4ProjectManager::Internal;

// Locate the compiler via path.
static QString gcceCommand(const QString &dir)
{
    ProjectExplorer::Environment env = ProjectExplorer::Environment::systemEnvironment();
    if (!dir.isEmpty()) {
        env.prependOrSetPath(dir + QLatin1String("/bin"));
        env.prependOrSetPath(dir);
    }
    QString gcce = QLatin1String("arm-none-symbianelf-gcc");
#ifdef Q_OS_WIN
    gcce += QLatin1String(".exe");
#endif
    const QString rc = env.searchInPath(gcce);
    if (debug && rc.isEmpty()) {
        const QString msg = QString::fromLatin1("GCCEToolChain: Unable to locate '%1' in '%2' (GCCE root: '%3')")
                            .arg(gcce, env.value(QLatin1String("PATH")), dir);
        qWarning("%s", qPrintable(msg));
        return gcce;
    }
    return rc;
}

// The GccToolChain base class constructor wants to know the gcc command
GCCEToolChain *GCCEToolChain::create(const S60Devices::Device &device,
                                     const QString &gcceRoot,
                                     ProjectExplorer::ToolChain::ToolChainType type)
{
    const QString gccCommand = gcceCommand(gcceRoot);
    const QFileInfo gccCommandFi(gccCommand);
    const QString binPath = gccCommandFi.isRelative() ? QString() : gccCommandFi.absolutePath();
    return new GCCEToolChain(device, binPath, gccCommand, type);
}

GCCEToolChain::GCCEToolChain(const S60Devices::Device &device,
                             const QString &gcceBinPath,
                             const QString &gcceCommand,
                             ProjectExplorer::ToolChain::ToolChainType type) :
    GccToolChain(gcceCommand),
    m_mixin(device),
    m_type(type),
    m_gcceBinPath(gcceBinPath)
{
    QTC_ASSERT(m_type == ProjectExplorer::ToolChain::GCCE || m_type == ProjectExplorer::ToolChain::GCCE_GNUPOC, return)
    if (debug)
        qDebug() << "GCCEToolChain on" << m_type << gcceCommand << gcceBinPath << m_mixin.device();
}

ToolChain::ToolChainType GCCEToolChain::type() const
{
    return m_type;
}

QByteArray GCCEToolChain::predefinedMacros()
{
    if (m_predefinedMacros.isEmpty()) {
        ProjectExplorer::GccToolChain::predefinedMacros();
        m_predefinedMacros += "\n"
                "#define __GCCE__\n"
                "#define __SYMBIAN32__\n";
    }
    return m_predefinedMacros;
}

QList<HeaderPath> GCCEToolChain::systemHeaderPaths()
{
    if (m_systemHeaderPaths.isEmpty()) {
        GccToolChain::systemHeaderPaths();
        switch (m_type) {
        case ProjectExplorer::ToolChain::GCCE:
            m_systemHeaderPaths += m_mixin.epocHeaderPaths();
            break;
        case ProjectExplorer::ToolChain::GCCE_GNUPOC:
            m_systemHeaderPaths += m_mixin.gnuPocHeaderPaths();
            break;
        default:
            break;
        }
    }
    return m_systemHeaderPaths;
}

void GCCEToolChain::addToEnvironment(ProjectExplorer::Environment &env)
{
    if (debug)
        qDebug() << "GCCEToolChain::addToEnvironment" << m_type << gcc() << m_gcceBinPath<< m_mixin.device();

    if (!m_gcceBinPath.isEmpty())
        env.prependOrSetPath(m_gcceBinPath);
    switch (m_type) {
    case ProjectExplorer::ToolChain::GCCE:
        m_mixin.addEpocToEnvironment(&env);
        break;
    case ProjectExplorer::ToolChain::GCCE_GNUPOC:
        m_mixin.addGnuPocToEnvironment(&env);
        break;
    default:
        break;
    }
    QString version = gcceVersion();
    version = version.remove(QLatin1Char('.'));
    env.set(QString::fromLatin1("SBS_GCCE") + version + QLatin1String("BIN"), QDir::toNativeSeparators(m_gcceBinPath));
}

QString GCCEToolChain::makeCommand() const
{
    return QLatin1String("make");
}

bool GCCEToolChain::equals(ToolChain *otherIn) const
{
    if (otherIn->type() != type())
                return false;
    const GCCEToolChain *other = static_cast<const GCCEToolChain *>(otherIn);
    return m_mixin == other->m_mixin
           && m_gcceBinPath == other->m_gcceBinPath
           && gcc() == other->gcc();
}

QString GCCEToolChain::gcceVersion() const
{
    if (m_gcceVersion.isEmpty()) {
        QString command = gcceCommand(m_gcceBinPath);
        if (command.isEmpty())
            return QString();
        QProcess gxx;
        QStringList arguments;
        arguments << QLatin1String("-dumpversion");
        ProjectExplorer::Environment env = ProjectExplorer::Environment::systemEnvironment();
        env.set(QLatin1String("LC_ALL"), QLatin1String("C"));   //override current locale settings
        gxx.setEnvironment(env.toStringList());
        gxx.setReadChannelMode(QProcess::MergedChannels);
        gxx.start(command, arguments);
        gxx.closeWriteChannel();
        gxx.waitForFinished();

        QString line;
        if (gxx.canReadLine()) {
            line = gxx.readLine();
            m_gcceVersion = line.trimmed();
        }
    }
    return m_gcceVersion;
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#ifndef ROCRAND_RNG_MRG32K3A_H_
#define ROCRAND_RNG_MRG32K3A_H_

#include <algorithm>
#include <hip/hip_runtime.h>

#include <rocrand.h>

#include "generator_type.hpp"
#include "device_engines.hpp"
#include "distributions.hpp"

namespace rocrand_host {
namespace detail {

    typedef ::rocrand_device::mrg32k3a_engine mrg32k3a_device_engine;

    __global__
    void init_engines_kernel(mrg32k3a_device_engine * engines,
                            unsigned long long seed,
                            unsigned long long offset)
    {
        const unsigned int engine_id = hipBlockIdx_x * hipBlockDim_x + hipThreadIdx_x;
        engines[engine_id] = mrg32k3a_device_engine(seed, engine_id, offset);
    }

    template<class Type, class Distribution>
    __global__
    void generate_kernel(mrg32k3a_device_engine * engines,
                         Type * data, const size_t n,
                         const Distribution distribution)
    {
        const unsigned int engine_id = hipBlockIdx_x * hipBlockDim_x + hipThreadIdx_x;
        unsigned int index = engine_id;
        unsigned int stride = hipGridDim_x * hipBlockDim_x;

        // Load device engine
        mrg32k3a_device_engine engine = engines[engine_id];

        while(index < n)
        {
            data[index] = distribution(engine());
            // Next position
            index += stride;
        }

        // Save engine with its state
        engines[engine_id] = engine;
    }

    template<class RealType, class Distribution>
    __global__
    void generate_normal_kernel(mrg32k3a_device_engine * engines,
                                RealType * data, const size_t n,
                                Distribution distribution)
    {
        typedef decltype(distribution(engines->next(), engines->next())) RealType2;

        const unsigned int engine_id = hipBlockIdx_x * hipBlockDim_x + hipThreadIdx_x;
        unsigned int index = engine_id;
        unsigned int stride = hipGridDim_x * hipBlockDim_x;

        // Load device engine
        mrg32k3a_device_engine engine = engines[engine_id];

        RealType2 * data2 = (RealType2 *)data;
        while(index < (n / 2))
        {
            data2[index] = distribution(engine(), engine());
            // Next position
            index += stride;
        }

        // First work-item saves the tail when n is not a multiple of 2
        if(engine_id == 0 && (n & 1) > 0)
        {
            RealType2 result = distribution(engine(), engine());
            // Save the tail
            data[n - 1] = result.x;
        }

        // Save engine with its state
        engines[engine_id] = engine;
    }

} // end namespace detail
} // end namespace rocrand_host

class rocrand_mrg32k3a : public rocrand_generator_type<ROCRAND_RNG_PSEUDO_MRG32K3A>
{
public:
    using base_type = rocrand_generator_type<ROCRAND_RNG_PSEUDO_MRG32K3A>;
    using engine_type = ::rocrand_host::detail::mrg32k3a_device_engine;

    rocrand_mrg32k3a(unsigned long long seed = 12345,
                     unsigned long long offset = 0,
                     hipStream_t stream = 0)
        : base_type(seed, offset, stream),
          m_engines_initialized(false), m_engines(NULL), m_engines_size(1024 * 256)
    {
        // Allocate device random number engines
        auto error = hipMalloc(&m_engines, sizeof(engine_type) * m_engines_size);
        if(error != hipSuccess)
        {
            throw ROCRAND_STATUS_ALLOCATION_FAILED;
        }
        if(m_seed == 0)
        {
            m_seed = ROCRAND_MRG32K3A_DEFAULT_SEED;
        }
    }

    ~rocrand_mrg32k3a()
    {
        hipFree(m_engines);
    }

    void reset()
    {
        m_engines_initialized = false;
    }

    /// Changes seed to \p seed and resets generator state.
    ///
    /// New seed value should not be zero. If \p seed_value is equal
    /// zero, value \p ROCRAND_MRG32K3A_DEFAULT_SEED is used instead.
    void set_seed(unsigned long long seed)
    {
        if(seed == 0)
        {
            seed = ROCRAND_MRG32K3A_DEFAULT_SEED;
        }
        m_seed = seed;
        m_engines_initialized = false;
    }

    void set_offset(unsigned long long offset)
    {
        m_offset = offset;
        m_engines_initialized = false;
    }

    rocrand_status init()
    {
        if (m_engines_initialized)
            return ROCRAND_STATUS_SUCCESS;

        #ifdef __HIP_PLATFORM_NVCC__
        const uint32_t threads = 128;
        const uint32_t max_blocks = 128;
        #else
        const uint32_t threads = 256;
        const uint32_t max_blocks = 1024;
        #endif
        const uint32_t blocks = max_blocks;

        hipLaunchKernelGGL(
            HIP_KERNEL_NAME(rocrand_host::detail::init_engines_kernel),
            dim3(blocks), dim3(threads), 0, m_stream,
            m_engines, m_seed, m_offset
        );
        // Check kernel status
        if(hipPeekAtLastError() != hipSuccess)
            return ROCRAND_STATUS_LAUNCH_FAILURE;

        m_engines_initialized = true;

        return ROCRAND_STATUS_SUCCESS;
    }

    template<class T, class Distribution = mrg_uniform_distribution<T> >
    rocrand_status generate(T * data, size_t data_size,
                            const Distribution& distribution = Distribution())
    {
        rocrand_status status = init();
        if (status != ROCRAND_STATUS_SUCCESS)
            return status;

        #ifdef __HIP_PLATFORM_NVCC__
        const uint32_t threads = 128;
        const uint32_t max_blocks = 128; // 512
        #else
        const uint32_t threads = 256;
        const uint32_t max_blocks = 1024;
        #endif
        const uint32_t blocks = max_blocks;

        hipLaunchKernelGGL(
            HIP_KERNEL_NAME(rocrand_host::detail::generate_kernel),
            dim3(blocks), dim3(threads), 0, m_stream,
            m_engines, data, data_size, distribution
        );
        // Check kernel status
        if(hipPeekAtLastError() != hipSuccess)
            return ROCRAND_STATUS_LAUNCH_FAILURE;

        return ROCRAND_STATUS_SUCCESS;
    }

    template<class T>
    rocrand_status generate_uniform(T * data, size_t data_size)
    {
        mrg_uniform_distribution<T> udistribution;
        return generate(data, data_size, udistribution);
    }

    template<class T>
    rocrand_status generate_normal(T * data, size_t data_size, T stddev, T mean)
    {
        rocrand_status status = init();
        if (status != ROCRAND_STATUS_SUCCESS)
            return status;

        #ifdef __HIP_PLATFORM_NVCC__
        const uint32_t threads = 128;
        const uint32_t max_blocks = 128; // 512
        #else
        const uint32_t threads = 256;
        const uint32_t max_blocks = 1024;
        #endif
        const uint32_t blocks = max_blocks;

        mrg_normal_distribution<T> distribution(mean, stddev);

        hipLaunchKernelGGL(
            HIP_KERNEL_NAME(rocrand_host::detail::generate_normal_kernel),
            dim3(blocks), dim3(threads), 0, m_stream,
            m_engines, data, data_size, distribution
        );
        // Check kernel status
        if(hipPeekAtLastError() != hipSuccess)
            return ROCRAND_STATUS_LAUNCH_FAILURE;

        return ROCRAND_STATUS_SUCCESS;
    }

    template<class T>
    rocrand_status generate_log_normal(T * data, size_t data_size, T stddev, T mean)
    {
        rocrand_status status = init();
        if (status != ROCRAND_STATUS_SUCCESS)
            return status;

        #ifdef __HIP_PLATFORM_NVCC__
        const uint32_t threads = 128;
        const uint32_t max_blocks = 128; // 512
        #else
        const uint32_t threads = 256;
        const uint32_t max_blocks = 1024;
        #endif
        const uint32_t blocks = max_blocks;

        mrg_log_normal_distribution<T> distribution(mean, stddev);

        hipLaunchKernelGGL(
            HIP_KERNEL_NAME(rocrand_host::detail::generate_normal_kernel),
            dim3(blocks), dim3(threads), 0, m_stream,
            m_engines, data, data_size, distribution
        );
        // Check kernel status
        if(hipPeekAtLastError() != hipSuccess)
            return ROCRAND_STATUS_LAUNCH_FAILURE;

        return ROCRAND_STATUS_SUCCESS;
    }

    rocrand_status generate_poisson(unsigned int * data, size_t data_size, double lambda)
    {
        try
        {
            poisson.set_lambda(lambda);
        }
        catch(rocrand_status status)
        {
            return status;
        }
        return generate(data, data_size, poisson.dis);
    }

private:
    bool m_engines_initialized;
    engine_type * m_engines;
    size_t m_engines_size;

    // For caching of Poisson for consecutive generations with the same lambda
    poisson_distribution_manager<> poisson;

    // m_seed from base_type
    // m_offset from base_type
};

#endif // ROCRAND_RNG_MRG32K3A_H_
<commit_msg>Reduced internal memory usage by MRG32K3A<commit_after>// Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#ifndef ROCRAND_RNG_MRG32K3A_H_
#define ROCRAND_RNG_MRG32K3A_H_

#include <algorithm>
#include <hip/hip_runtime.h>

#include <rocrand.h>

#include "generator_type.hpp"
#include "device_engines.hpp"
#include "distributions.hpp"

namespace rocrand_host {
namespace detail {

    typedef ::rocrand_device::mrg32k3a_engine mrg32k3a_device_engine;

    __global__
    void init_engines_kernel(mrg32k3a_device_engine * engines,
                            unsigned long long seed,
                            unsigned long long offset)
    {
        const unsigned int engine_id = hipBlockIdx_x * hipBlockDim_x + hipThreadIdx_x;
        engines[engine_id] = mrg32k3a_device_engine(seed, engine_id, offset);
    }

    template<class Type, class Distribution>
    __global__
    void generate_kernel(mrg32k3a_device_engine * engines,
                         Type * data, const size_t n,
                         const Distribution distribution)
    {
        const unsigned int engine_id = hipBlockIdx_x * hipBlockDim_x + hipThreadIdx_x;
        unsigned int index = engine_id;
        unsigned int stride = hipGridDim_x * hipBlockDim_x;

        // Load device engine
        mrg32k3a_device_engine engine = engines[engine_id];

        while(index < n)
        {
            data[index] = distribution(engine());
            // Next position
            index += stride;
        }

        // Save engine with its state
        engines[engine_id] = engine;
    }

    template<class RealType, class Distribution>
    __global__
    void generate_normal_kernel(mrg32k3a_device_engine * engines,
                                RealType * data, const size_t n,
                                Distribution distribution)
    {
        typedef decltype(distribution(engines->next(), engines->next())) RealType2;

        const unsigned int engine_id = hipBlockIdx_x * hipBlockDim_x + hipThreadIdx_x;
        unsigned int index = engine_id;
        unsigned int stride = hipGridDim_x * hipBlockDim_x;

        // Load device engine
        mrg32k3a_device_engine engine = engines[engine_id];

        RealType2 * data2 = (RealType2 *)data;
        while(index < (n / 2))
        {
            data2[index] = distribution(engine(), engine());
            // Next position
            index += stride;
        }

        // First work-item saves the tail when n is not a multiple of 2
        if(engine_id == 0 && (n & 1) > 0)
        {
            RealType2 result = distribution(engine(), engine());
            // Save the tail
            data[n - 1] = result.x;
        }

        // Save engine with its state
        engines[engine_id] = engine;
    }

} // end namespace detail
} // end namespace rocrand_host

class rocrand_mrg32k3a : public rocrand_generator_type<ROCRAND_RNG_PSEUDO_MRG32K3A>
{
public:
    using base_type = rocrand_generator_type<ROCRAND_RNG_PSEUDO_MRG32K3A>;
    using engine_type = ::rocrand_host::detail::mrg32k3a_device_engine;

    rocrand_mrg32k3a(unsigned long long seed = 12345,
                     unsigned long long offset = 0,
                     hipStream_t stream = 0)
        : base_type(seed, offset, stream),
          m_engines_initialized(false), m_engines(NULL), m_engines_size(256 * 256)
    {
        // Allocate device random number engines
        auto error = hipMalloc(&m_engines, sizeof(engine_type) * m_engines_size);
        if(error != hipSuccess)
        {
            throw ROCRAND_STATUS_ALLOCATION_FAILED;
        }
        if(m_seed == 0)
        {
            m_seed = ROCRAND_MRG32K3A_DEFAULT_SEED;
        }
    }

    ~rocrand_mrg32k3a()
    {
        hipFree(m_engines);
    }

    void reset()
    {
        m_engines_initialized = false;
    }

    /// Changes seed to \p seed and resets generator state.
    ///
    /// New seed value should not be zero. If \p seed_value is equal
    /// zero, value \p ROCRAND_MRG32K3A_DEFAULT_SEED is used instead.
    void set_seed(unsigned long long seed)
    {
        if(seed == 0)
        {
            seed = ROCRAND_MRG32K3A_DEFAULT_SEED;
        }
        m_seed = seed;
        m_engines_initialized = false;
    }

    void set_offset(unsigned long long offset)
    {
        m_offset = offset;
        m_engines_initialized = false;
    }

    rocrand_status init()
    {
        if (m_engines_initialized)
            return ROCRAND_STATUS_SUCCESS;

        #ifdef __HIP_PLATFORM_NVCC__
        const uint32_t threads = 128;
        const uint32_t max_blocks = 128;
        #else
        const uint32_t threads = 256;
        const uint32_t max_blocks = 256;
        #endif
        const uint32_t blocks = max_blocks;

        hipLaunchKernelGGL(
            HIP_KERNEL_NAME(rocrand_host::detail::init_engines_kernel),
            dim3(blocks), dim3(threads), 0, m_stream,
            m_engines, m_seed, m_offset
        );
        // Check kernel status
        if(hipPeekAtLastError() != hipSuccess)
            return ROCRAND_STATUS_LAUNCH_FAILURE;

        m_engines_initialized = true;

        return ROCRAND_STATUS_SUCCESS;
    }

    template<class T, class Distribution = mrg_uniform_distribution<T> >
    rocrand_status generate(T * data, size_t data_size,
                            const Distribution& distribution = Distribution())
    {
        rocrand_status status = init();
        if (status != ROCRAND_STATUS_SUCCESS)
            return status;

        #ifdef __HIP_PLATFORM_NVCC__
        const uint32_t threads = 128;
        const uint32_t max_blocks = 128; // 512
        #else
        const uint32_t threads = 256;
        const uint32_t max_blocks = 256;
        #endif
        const uint32_t blocks = max_blocks;

        hipLaunchKernelGGL(
            HIP_KERNEL_NAME(rocrand_host::detail::generate_kernel),
            dim3(blocks), dim3(threads), 0, m_stream,
            m_engines, data, data_size, distribution
        );
        // Check kernel status
        if(hipPeekAtLastError() != hipSuccess)
            return ROCRAND_STATUS_LAUNCH_FAILURE;

        return ROCRAND_STATUS_SUCCESS;
    }

    template<class T>
    rocrand_status generate_uniform(T * data, size_t data_size)
    {
        mrg_uniform_distribution<T> udistribution;
        return generate(data, data_size, udistribution);
    }

    template<class T>
    rocrand_status generate_normal(T * data, size_t data_size, T stddev, T mean)
    {
        rocrand_status status = init();
        if (status != ROCRAND_STATUS_SUCCESS)
            return status;

        #ifdef __HIP_PLATFORM_NVCC__
        const uint32_t threads = 128;
        const uint32_t max_blocks = 128; // 512
        #else
        const uint32_t threads = 256;
        const uint32_t max_blocks = 256;
        #endif
        const uint32_t blocks = max_blocks;

        mrg_normal_distribution<T> distribution(mean, stddev);

        hipLaunchKernelGGL(
            HIP_KERNEL_NAME(rocrand_host::detail::generate_normal_kernel),
            dim3(blocks), dim3(threads), 0, m_stream,
            m_engines, data, data_size, distribution
        );
        // Check kernel status
        if(hipPeekAtLastError() != hipSuccess)
            return ROCRAND_STATUS_LAUNCH_FAILURE;

        return ROCRAND_STATUS_SUCCESS;
    }

    template<class T>
    rocrand_status generate_log_normal(T * data, size_t data_size, T stddev, T mean)
    {
        rocrand_status status = init();
        if (status != ROCRAND_STATUS_SUCCESS)
            return status;

        #ifdef __HIP_PLATFORM_NVCC__
        const uint32_t threads = 128;
        const uint32_t max_blocks = 128; // 512
        #else
        const uint32_t threads = 256;
        const uint32_t max_blocks = 256;
        #endif
        const uint32_t blocks = max_blocks;

        mrg_log_normal_distribution<T> distribution(mean, stddev);

        hipLaunchKernelGGL(
            HIP_KERNEL_NAME(rocrand_host::detail::generate_normal_kernel),
            dim3(blocks), dim3(threads), 0, m_stream,
            m_engines, data, data_size, distribution
        );
        // Check kernel status
        if(hipPeekAtLastError() != hipSuccess)
            return ROCRAND_STATUS_LAUNCH_FAILURE;

        return ROCRAND_STATUS_SUCCESS;
    }

    rocrand_status generate_poisson(unsigned int * data, size_t data_size, double lambda)
    {
        try
        {
            poisson.set_lambda(lambda);
        }
        catch(rocrand_status status)
        {
            return status;
        }
        return generate(data, data_size, poisson.dis);
    }

private:
    bool m_engines_initialized;
    engine_type * m_engines;
    size_t m_engines_size;

    // For caching of Poisson for consecutive generations with the same lambda
    poisson_distribution_manager<> poisson;

    // m_seed from base_type
    // m_offset from base_type
};

#endif // ROCRAND_RNG_MRG32K3A_H_
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  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. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
// Class header file.
#include "XResultTreeFrag.hpp"

#include <XalanDOM/XalanNodeList.hpp>
#include <XalanDOM/XalanText.hpp>

#include <PlatformSupport/DOMStringHelper.hpp>
#include <PlatformSupport/DoubleSupport.hpp>

#include <DOMSupport/DOMServices.hpp>

#include "NodeRefListBase.hpp"
#include "ResultTreeFragBase.hpp"
#include "XObjectTypeCallback.hpp"

XResultTreeFrag::XResultTreeFrag(BorrowReturnResultTreeFrag&	val) :
	XObject(eTypeResultTreeFrag),
	m_value(val),
	m_cachedStringValue(),
	m_cachedNumberValue(0.0)
#if XALAN_RTREEFRAG_TO_NODESET_CONVERSION
	, m_nodeRefListBaseProxy(*this)
#endif
{
}

XResultTreeFrag::XResultTreeFrag(
			const XResultTreeFrag&	source,
			bool					deepClone) :
	XObject(source),
	m_value(source.m_value.clone(deepClone)),
	m_cachedStringValue(source.m_cachedStringValue),
	m_cachedNumberValue(source.m_cachedNumberValue)
#if XALAN_RTREEFRAG_TO_NODESET_CONVERSION
	, m_nodeRefListBaseProxy(*this)
#endif
{
}

XResultTreeFrag::~XResultTreeFrag()
{
}

#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
XObject*
#else
XResultTreeFrag*
#endif
XResultTreeFrag::clone(void*	theAddress) const
{
	return theAddress == 0 ? new XResultTreeFrag(*this) : new (theAddress) XResultTreeFrag(*this);
};

XalanDOMString
XResultTreeFrag::getTypeString() const
{
	return XALAN_STATIC_UCODE_STRING("#RESULT_TREE_FRAG");
}

double
XResultTreeFrag::num() const
{
	if (m_cachedNumberValue == 0.0)
	{
#if defined(XALAN_NO_MUTABLE)
		((XResultTreeFrag*)this)->m_cachedNumberValue = DoubleSupport::toDouble(str());
#else
		m_cachedNumberValue = DoubleSupport::toDouble(str());
#endif
	}

	return m_cachedNumberValue;
}

bool
XResultTreeFrag::boolean() const
{
	// Result tree fragments always evaluate to true.
	return true;
}

const XalanDOMString&
XResultTreeFrag::str() const
{
	if (isEmpty(m_cachedStringValue) == true)
	{
#if defined(XALAN_NO_MUTABLE)
		DOMServices::getNodeData(*m_value, ((XResultTreeFrag*)this)->m_cachedStringValue);
#else
		DOMServices::getNodeData(*m_value, m_cachedStringValue);
#endif
	}

	return m_cachedStringValue;
}

void
XResultTreeFrag::str(
			FormatterListener&	formatterListener,
			MemberFunctionPtr	function) const
{
	if (isEmpty(m_cachedStringValue) == false)
	{
		(formatterListener.*function)(c_wstr(m_cachedStringValue), length(m_cachedStringValue));
	}
	else
	{
		DOMServices::getNodeData(*m_value, formatterListener, function);
	}
}

void
XResultTreeFrag::str(XalanDOMString&	theBuffer) const
{
	if (isEmpty(m_cachedStringValue) == false)
	{
		append(theBuffer, m_cachedStringValue);
	}
	else
	{
		DOMServices::getNodeData(*m_value, theBuffer);
	}
}

const ResultTreeFragBase&
XResultTreeFrag::rtree(XPathExecutionContext&	/* executionContext */) const
{
	return *m_value.get();
}

const ResultTreeFragBase&
XResultTreeFrag::rtree() const
{
	return *m_value.get();
}

const NodeRefListBase&
XResultTreeFrag::nodeset() const
{
#if XALAN_RTREEFRAG_TO_NODESET_CONVERSION
	return m_nodeRefListBaseProxy;
#else
	return ParentType::nodeset();
#endif
}

void
XResultTreeFrag::ProcessXObjectTypeCallback(XObjectTypeCallback&	theCallbackObject)
{
	theCallbackObject.ResultTreeFragment(*this,
										 rtree());
}

void
XResultTreeFrag::ProcessXObjectTypeCallback(XObjectTypeCallback&	theCallbackObject) const
{
	theCallbackObject.ResultTreeFragment(*this,
										 rtree());
}

XalanNode*
XResultTreeFrag::item(unsigned int	index) const
{
	assert(m_value.get() != 0);

	XalanNode*	theCurrentChild = m_value->getFirstChild();

	for(unsigned int i = 0; i < index && theCurrentChild != 0; ++i)
	{
		theCurrentChild = theCurrentChild->getNextSibling();
	}

	return theCurrentChild;
}

unsigned int
XResultTreeFrag::getLength() const
{
	return 1;
	assert(m_value.get() != 0);

	unsigned int	theLength = 0;

	XalanNode*	theCurrentChild = m_value->getFirstChild();

	while(theCurrentChild != 0)
	{
		++theLength;

		theCurrentChild = theCurrentChild->getNextSibling();
	}

	return theLength;
}

unsigned int
XResultTreeFrag::indexOf(const XalanNode*	theNode) const
{
	unsigned	theIndex = 0;
	bool		fFound = false;

	XalanNode*	theCurrentChild = m_value->getFirstChild();

	while(theCurrentChild != 0 && fFound == false)
	{
		if (theCurrentChild == theNode)
		{
			fFound = true;
		}
		else
		{
			++theIndex;

			theCurrentChild = theCurrentChild->getNextSibling();
		}
	}

	return fFound == true ? theIndex : NodeRefListBase::npos;
}

XResultTreeFrag::NodeRefListBaseProxy::NodeRefListBaseProxy(const XResultTreeFrag&	theXResultTreeFrag) :
	NodeRefListBase(),
	m_xresultTreeFrag(theXResultTreeFrag)
{
}

XResultTreeFrag::NodeRefListBaseProxy::~NodeRefListBaseProxy()
{
}

XalanNode*
XResultTreeFrag::NodeRefListBaseProxy::item(unsigned int	index) const
{
	if (index == 0)
	{
		return m_xresultTreeFrag.m_value.get();
	}
	else
	{
		return 0;
	}
}

unsigned int
XResultTreeFrag::NodeRefListBaseProxy::getLength() const
{
	return 1;
}

unsigned int
XResultTreeFrag::NodeRefListBaseProxy::indexOf(const XalanNode*	theNode) const
{
	if (theNode == m_xresultTreeFrag.m_value.get())
	{
		return 0;
	}
	else
	{
		return NodeRefListBase::npos;
	}
}

void
XResultTreeFrag::release()
{
	m_value.release();

	clear(m_cachedStringValue);

	m_cachedNumberValue = 0.0;
}

void
XResultTreeFrag::set(BorrowReturnResultTreeFrag&	theValue)
{
	release();

	m_value = theValue;
}
<commit_msg>Fixed bugs with interpreting ResultTreeFrags as node-sets.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  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. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
// Class header file.
#include "XResultTreeFrag.hpp"

#include <XalanDOM/XalanNodeList.hpp>
#include <XalanDOM/XalanText.hpp>

#include <PlatformSupport/DOMStringHelper.hpp>
#include <PlatformSupport/DoubleSupport.hpp>

#include <DOMSupport/DOMServices.hpp>

#include "NodeRefListBase.hpp"
#include "ResultTreeFragBase.hpp"
#include "XObjectTypeCallback.hpp"

XResultTreeFrag::XResultTreeFrag(BorrowReturnResultTreeFrag&	val) :
	XObject(eTypeResultTreeFrag),
	m_value(val),
	m_cachedStringValue(),
	m_cachedNumberValue(0.0)
#if XALAN_RTREEFRAG_TO_NODESET_CONVERSION
	, m_nodeRefListBaseProxy(*this)
#endif
{
}

XResultTreeFrag::XResultTreeFrag(
			const XResultTreeFrag&	source,
			bool					deepClone) :
	XObject(source),
	m_value(source.m_value.clone(deepClone)),
	m_cachedStringValue(source.m_cachedStringValue),
	m_cachedNumberValue(source.m_cachedNumberValue)
#if XALAN_RTREEFRAG_TO_NODESET_CONVERSION
	, m_nodeRefListBaseProxy(*this)
#endif
{
}

XResultTreeFrag::~XResultTreeFrag()
{
}

#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
XObject*
#else
XResultTreeFrag*
#endif
XResultTreeFrag::clone(void*	theAddress) const
{
	return theAddress == 0 ? new XResultTreeFrag(*this) : new (theAddress) XResultTreeFrag(*this);
};

XalanDOMString
XResultTreeFrag::getTypeString() const
{
	return XALAN_STATIC_UCODE_STRING("#RESULT_TREE_FRAG");
}

double
XResultTreeFrag::num() const
{
	if (m_cachedNumberValue == 0.0)
	{
#if defined(XALAN_NO_MUTABLE)
		((XResultTreeFrag*)this)->m_cachedNumberValue = DoubleSupport::toDouble(str());
#else
		m_cachedNumberValue = DoubleSupport::toDouble(str());
#endif
	}

	return m_cachedNumberValue;
}

bool
XResultTreeFrag::boolean() const
{
	// Result tree fragments always evaluate to true.
	return true;
}

const XalanDOMString&
XResultTreeFrag::str() const
{
	if (isEmpty(m_cachedStringValue) == true)
	{
#if defined(XALAN_NO_MUTABLE)
		DOMServices::getNodeData(*m_value, ((XResultTreeFrag*)this)->m_cachedStringValue);
#else
		DOMServices::getNodeData(*m_value, m_cachedStringValue);
#endif
	}

	return m_cachedStringValue;
}

void
XResultTreeFrag::str(
			FormatterListener&	formatterListener,
			MemberFunctionPtr	function) const
{
	if (isEmpty(m_cachedStringValue) == false)
	{
		(formatterListener.*function)(c_wstr(m_cachedStringValue), length(m_cachedStringValue));
	}
	else
	{
		DOMServices::getNodeData(*m_value, formatterListener, function);
	}
}

void
XResultTreeFrag::str(XalanDOMString&	theBuffer) const
{
	if (isEmpty(m_cachedStringValue) == false)
	{
		append(theBuffer, m_cachedStringValue);
	}
	else
	{
		DOMServices::getNodeData(*m_value, theBuffer);
	}
}

const ResultTreeFragBase&
XResultTreeFrag::rtree(XPathExecutionContext&	/* executionContext */) const
{
	return *m_value.get();
}

const ResultTreeFragBase&
XResultTreeFrag::rtree() const
{
	return *m_value.get();
}

const NodeRefListBase&
XResultTreeFrag::nodeset() const
{
#if XALAN_RTREEFRAG_TO_NODESET_CONVERSION
	return m_nodeRefListBaseProxy;
#else
	return ParentType::nodeset();
#endif
}

void
XResultTreeFrag::ProcessXObjectTypeCallback(XObjectTypeCallback&	theCallbackObject)
{
	theCallbackObject.ResultTreeFragment(*this,
										 rtree());
}

void
XResultTreeFrag::ProcessXObjectTypeCallback(XObjectTypeCallback&	theCallbackObject) const
{
	theCallbackObject.ResultTreeFragment(*this,
										 rtree());
}

XalanNode*
XResultTreeFrag::item(unsigned int	index) const
{
	return index == 0 ? m_value.get() : 0;
}

unsigned int
XResultTreeFrag::getLength() const
{
	return 1;
}

unsigned int
XResultTreeFrag::indexOf(const XalanNode*	theNode) const
{
	return theNode == m_value.get() ? 0 : NodeRefListBase::npos;
}

XResultTreeFrag::NodeRefListBaseProxy::NodeRefListBaseProxy(const XResultTreeFrag&	theXResultTreeFrag) :
	NodeRefListBase(),
	m_xresultTreeFrag(theXResultTreeFrag)
{
}

XResultTreeFrag::NodeRefListBaseProxy::~NodeRefListBaseProxy()
{
}

XalanNode*
XResultTreeFrag::NodeRefListBaseProxy::item(unsigned int	index) const
{
	return m_xresultTreeFrag.item(index);
}

unsigned int
XResultTreeFrag::NodeRefListBaseProxy::getLength() const
{
	return m_xresultTreeFrag.getLength();
}

unsigned int
XResultTreeFrag::NodeRefListBaseProxy::indexOf(const XalanNode*	theNode) const
{
	return m_xresultTreeFrag.indexOf(theNode);
}

void
XResultTreeFrag::release()
{
	m_value.release();

	clear(m_cachedStringValue);

	m_cachedNumberValue = 0.0;
}

void
XResultTreeFrag::set(BorrowReturnResultTreeFrag&	theValue)
{
	release();

	m_value = theValue;
}
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999-2002 The Apache Software Foundation.  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. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 * $ Id: $

 */

#if !defined(XALAN_XSLTRESULTTARGET_HEADER_GUARD)
#define XALAN_XSLTRESULTTARGET_HEADER_GUARD

// Base include file.  Must be first.
#include "XSLTDefinitions.hpp"

#if defined(XALAN_CLASSIC_IOSTREAMS)
class ostream;
#else
#include <iosfwd>
#endif

#include <XalanDOM/XalanDOMString.hpp>

XALAN_CPP_NAMESPACE_BEGIN

class FormatterListener;
class XalanDocument;
class XalanDocumentFragment;
class XalanElement;
class Writer;

class XALAN_XSLT_EXPORT XSLTResultTarget
{
public:

#if defined(XALAN_NO_STD_NAMESPACE)
	typedef ostream			StreamType;
#else
	typedef std::ostream	StreamType;
#endif

	explicit
	XSLTResultTarget();

	/**
	 * Create a new output target with a file name.
	 *
	 * @param fileName valid system file name
	 */
	XSLTResultTarget(const XalanDOMString&	fileName);

	/**
	 * Create a new output target with a file name.
	 *
	 * @param fileName valid system file name
	 */
	XSLTResultTarget(const XalanDOMChar*	fileName);

	/**
	 * Create a new output target with a file name.
	 *
	 * @param fileName valid system file name
	 */
	XSLTResultTarget(const char*	fileName);

	/**
	 * Create a new output target with a stream.
	 *
	 * @param byteStream a pointer to a std ostream for the output
	 */
	XSLTResultTarget(StreamType*	theStream);

	/**
	 * Create a new output target with a stream.
	 *
	 * @param byteStream a reference to a std ostream for the output
	 */
	XSLTResultTarget(StreamType&	theStream);

	/**
	 * Create a new output target with a character stream.
	 *
	 * @param characterStream pointer to character stream where the results
	 *                        will be written
	 */
	XSLTResultTarget(Writer*	characterStream);

	/**
	 * Create a new output target with a DOM document.
	 *
	 * @param n root of DOM node tree that holds results
	 */
	XSLTResultTarget(XalanDocument*		document);

	/**
	 * Create a new output target with a DOM document fragment.
	 *
	 * @param n root of DOM node tree that holds results
	 */
	XSLTResultTarget(XalanDocumentFragment*		documentFragment);

	/**
	 * Create a new output target with a DOM element.
	 *
	 * @param n root of DOM node tree that holds results
	 */
	XSLTResultTarget(XalanElement*	element);

	/**
	 * Create a new output target with a FormatterListener.
	 *
	 * @param flistener A FormatterListener instance for result tree events.
	 */
	XSLTResultTarget(FormatterListener&		flistener);

	~XSLTResultTarget();

	/**
	 * Set the file name where the results will be written.
	 *
	 * @param fileName system identifier as a string
	 */
	void
	setFileName(const XalanDOMString&	fileName)
	{
		m_fileName = fileName;
	}

	/**
	 * Get the file name where the results will be written to.
	 *
	 * @return file name string
	 */
	const XalanDOMString&
	getFileName() const
	{
		return m_fileName;
	}

	/**
	 * Set the byte stream for this output target.
	 *
	 * @param byteStream pointer to byte stream that will contain the result
	 *                   document
	 */
	void
	setByteStream(StreamType*			byteStream)
	{
		m_byteStream = byteStream;
	}

	/**
	 * Get the byte stream for this output target.
	 *
	 * @return pointer to byte stream, or null if none was supplied.
	 */
	StreamType*
	getByteStream() const
	{
		return m_byteStream;
	}

	/**
	 * Set the character encoding, if known.
	 *
	 * @param encoding new encoding string
	 */
	void
	setEncoding(const XalanDOMString&	encoding)
	{
		m_encoding = encoding;
	}

	/**
	 * Get the character encoding in use.
	 *
	 * @return encoding string, or empty string if none was supplied.
	 */
	const XalanDOMString&
	getEncoding() const
	{
		return m_encoding;
	}

	/**
	 * Set the character stream for this output target.
	 *
	 * @param characterStream pointer to character stream that will contain
	 *                        the result document
	 */
	void
	setCharacterStream(Writer*	characterStream)
	{
		m_characterStream = characterStream;
	}

	/**
	 * Get the character stream for this output target.
	 *
	 * @return pointer to character stream, or null if none was supplied.
	 */
	Writer*
	getCharacterStream() const
	{
		return m_characterStream;
	}

	bool
	hasDOMTarget() const
	{
		return m_document != 0 || m_documentFragment != 0 || m_element != 0;
	}

	/**
	 * Set the document node that will contain the result nodes.
	 *
	 * @param node DOM node to contain results
	 */
	void
	setDocument(XalanDocument*		document)
	{
		m_document = document;

		m_documentFragment = 0;
		m_element = 0;
	}

	/**
	 * Get the document node that will contain the result nodes.
	 *
	 * @return a pointer to the document node
	 */
	XalanDocument*
	getDocument() const
	{
		return m_document;
	}

	/**
	 * Set the document fragment node that will contain the result nodes.
	 *
	 * @param node DOM node to contain results
	 */
	void
	setDocumentFragment(XalanDocumentFragment*	documentFragment)
	{
		m_documentFragment = documentFragment;

		m_document = 0;
		m_element = 0;
	}

	/**
	 * Get the document node that will contain the result nodes.
	 *
	 * @return a pointer to the document node
	 */
	XalanDocumentFragment*
	getDocumentFragment() const
	{
		return m_documentFragment;
	}

	/**
	 * Set the element node that will contain the result nodes.
	 *
	 * @param node DOM node to contain results
	 */
	void
	setElement(XalanElement*	element)
	{
		m_element = element;

		m_documentFragment = 0;
		m_document = 0;
	}

	/**
	 * Get the document node that will contain the result nodes.
	 *
	 * @return a pointer to the document node
	 */
	XalanElement*
	getElement() const
	{
		return m_element;
	}

	/**
	 * Set a SAX DocumentHandler to process the result tree events.
	 *
	 * @param handler pointer to new handler
	 */
	void
	setDocumentHandler(FormatterListener*	handler)
	{
		m_formatterListener = handler;
	}

	/**
	 * Get the SAX DocumentHandler that will process the result tree events.
	 *
	 * @return pointer to current handler
	 */
	FormatterListener*
	getDocumentHandler() const
	{
		return m_formatterListener;
	}

	/**
	 * Set a FormatterListener to process the result tree events.
	 *
	 * @param handler pointer to new listener
	 */
	void
	setFormatterListener(FormatterListener*		handler)
	{
		m_formatterListener = handler;
	}

	/**
	 * Get the FormatterListener that will process the result tree events.
	 *
	 * @return pointer to new listener
	 */
	FormatterListener*
	getFormatterListener() const
	{
		return m_formatterListener;
	}

private:

	XalanDOMString			m_fileName;

	StreamType*				m_byteStream;

	XalanDOMString			m_encoding;

	Writer*					m_characterStream;

	XalanDocument*			m_document;

	XalanDocumentFragment*	m_documentFragment;

	XalanElement*			m_element;

	FormatterListener*		m_formatterListener;
};

XALAN_CPP_NAMESPACE_END

#endif	// XALAN_XSLTRESULTTARGET_HEADER_GUARD
<commit_msg>Added set accessor for const char*.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999-2002 The Apache Software Foundation.  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. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 * $ Id: $

 */

#if !defined(XALAN_XSLTRESULTTARGET_HEADER_GUARD)
#define XALAN_XSLTRESULTTARGET_HEADER_GUARD

// Base include file.  Must be first.
#include "XSLTDefinitions.hpp"

#if defined(XALAN_CLASSIC_IOSTREAMS)
class ostream;
#else
#include <iosfwd>
#endif

#include <XalanDOM/XalanDOMString.hpp>

XALAN_CPP_NAMESPACE_BEGIN

class FormatterListener;
class XalanDocument;
class XalanDocumentFragment;
class XalanElement;
class Writer;

class XALAN_XSLT_EXPORT XSLTResultTarget
{
public:

#if defined(XALAN_NO_STD_NAMESPACE)
	typedef ostream			StreamType;
#else
	typedef std::ostream	StreamType;
#endif

	explicit
	XSLTResultTarget();

	/**
	 * Create a new output target with a file name.
	 *
	 * @param fileName valid system file name
	 */
	XSLTResultTarget(const XalanDOMString&	fileName);

	/**
	 * Create a new output target with a file name.
	 *
	 * @param fileName valid system file name
	 */
	XSLTResultTarget(const XalanDOMChar*	fileName);

	/**
	 * Create a new output target with a file name.
	 *
	 * @param fileName valid system file name
	 */
	XSLTResultTarget(const char*	fileName);

	/**
	 * Create a new output target with a stream.
	 *
	 * @param byteStream a pointer to a std ostream for the output
	 */
	XSLTResultTarget(StreamType*	theStream);

	/**
	 * Create a new output target with a stream.
	 *
	 * @param byteStream a reference to a std ostream for the output
	 */
	XSLTResultTarget(StreamType&	theStream);

	/**
	 * Create a new output target with a character stream.
	 *
	 * @param characterStream pointer to character stream where the results
	 *                        will be written
	 */
	XSLTResultTarget(Writer*	characterStream);

	/**
	 * Create a new output target with a DOM document.
	 *
	 * @param n root of DOM node tree that holds results
	 */
	XSLTResultTarget(XalanDocument*		document);

	/**
	 * Create a new output target with a DOM document fragment.
	 *
	 * @param n root of DOM node tree that holds results
	 */
	XSLTResultTarget(XalanDocumentFragment*		documentFragment);

	/**
	 * Create a new output target with a DOM element.
	 *
	 * @param n root of DOM node tree that holds results
	 */
	XSLTResultTarget(XalanElement*	element);

	/**
	 * Create a new output target with a FormatterListener.
	 *
	 * @param flistener A FormatterListener instance for result tree events.
	 */
	XSLTResultTarget(FormatterListener&		flistener);

	~XSLTResultTarget();

	/**
	 * Set the file name where the results will be written.
	 *
	 * @param fileName system identifier as a string
	 */
	void
	setFileName(const char*		fileName)
	{
		if (fileName == 0)
		{
			m_fileName.clear();
		}
		else
		{
			m_fileName = fileName;
		}
	}

	/**
	 * Set the file name where the results will be written.
	 *
	 * @param fileName system identifier as a string
	 */
	void
	setFileName(const XalanDOMString&	fileName)
	{
		m_fileName = fileName;
	}

	/**
	 * Get the file name where the results will be written to.
	 *
	 * @return file name string
	 */
	const XalanDOMString&
	getFileName() const
	{
		return m_fileName;
	}

	/**
	 * Set the byte stream for this output target.
	 *
	 * @param byteStream pointer to byte stream that will contain the result
	 *                   document
	 */
	void
	setByteStream(StreamType*			byteStream)
	{
		m_byteStream = byteStream;
	}

	/**
	 * Get the byte stream for this output target.
	 *
	 * @return pointer to byte stream, or null if none was supplied.
	 */
	StreamType*
	getByteStream() const
	{
		return m_byteStream;
	}

	/**
	 * Set the character encoding, if known.
	 *
	 * @param encoding new encoding string
	 */
	void
	setEncoding(const XalanDOMString&	encoding)
	{
		m_encoding = encoding;
	}

	/**
	 * Get the character encoding in use.
	 *
	 * @return encoding string, or empty string if none was supplied.
	 */
	const XalanDOMString&
	getEncoding() const
	{
		return m_encoding;
	}

	/**
	 * Set the character stream for this output target.
	 *
	 * @param characterStream pointer to character stream that will contain
	 *                        the result document
	 */
	void
	setCharacterStream(Writer*	characterStream)
	{
		m_characterStream = characterStream;
	}

	/**
	 * Get the character stream for this output target.
	 *
	 * @return pointer to character stream, or null if none was supplied.
	 */
	Writer*
	getCharacterStream() const
	{
		return m_characterStream;
	}

	bool
	hasDOMTarget() const
	{
		return m_document != 0 || m_documentFragment != 0 || m_element != 0;
	}

	/**
	 * Set the document node that will contain the result nodes.
	 *
	 * @param node DOM node to contain results
	 */
	void
	setDocument(XalanDocument*		document)
	{
		m_document = document;

		m_documentFragment = 0;
		m_element = 0;
	}

	/**
	 * Get the document node that will contain the result nodes.
	 *
	 * @return a pointer to the document node
	 */
	XalanDocument*
	getDocument() const
	{
		return m_document;
	}

	/**
	 * Set the document fragment node that will contain the result nodes.
	 *
	 * @param node DOM node to contain results
	 */
	void
	setDocumentFragment(XalanDocumentFragment*	documentFragment)
	{
		m_documentFragment = documentFragment;

		m_document = 0;
		m_element = 0;
	}

	/**
	 * Get the document node that will contain the result nodes.
	 *
	 * @return a pointer to the document node
	 */
	XalanDocumentFragment*
	getDocumentFragment() const
	{
		return m_documentFragment;
	}

	/**
	 * Set the element node that will contain the result nodes.
	 *
	 * @param node DOM node to contain results
	 */
	void
	setElement(XalanElement*	element)
	{
		m_element = element;

		m_documentFragment = 0;
		m_document = 0;
	}

	/**
	 * Get the document node that will contain the result nodes.
	 *
	 * @return a pointer to the document node
	 */
	XalanElement*
	getElement() const
	{
		return m_element;
	}

	/**
	 * Set a SAX DocumentHandler to process the result tree events.
	 *
	 * @param handler pointer to new handler
	 */
	void
	setDocumentHandler(FormatterListener*	handler)
	{
		m_formatterListener = handler;
	}

	/**
	 * Get the SAX DocumentHandler that will process the result tree events.
	 *
	 * @return pointer to current handler
	 */
	FormatterListener*
	getDocumentHandler() const
	{
		return m_formatterListener;
	}

	/**
	 * Set a FormatterListener to process the result tree events.
	 *
	 * @param handler pointer to new listener
	 */
	void
	setFormatterListener(FormatterListener*		handler)
	{
		m_formatterListener = handler;
	}

	/**
	 * Get the FormatterListener that will process the result tree events.
	 *
	 * @return pointer to new listener
	 */
	FormatterListener*
	getFormatterListener() const
	{
		return m_formatterListener;
	}

private:

	XalanDOMString			m_fileName;

	StreamType*				m_byteStream;

	XalanDOMString			m_encoding;

	Writer*					m_characterStream;

	XalanDocument*			m_document;

	XalanDocumentFragment*	m_documentFragment;

	XalanElement*			m_element;

	FormatterListener*		m_formatterListener;
};

XALAN_CPP_NAMESPACE_END

#endif	// XALAN_XSLTRESULTTARGET_HEADER_GUARD
<|endoftext|>


<commit_before>/**
 * @file test_hsv_aux.cpp
 * @brief Test for HSV color histogram auxiliary functions
 * @author Paolo D'Apice
 */

#define BOOST_TEST_MODULE hsv_aux
#include <boost/test/unit_test.hpp>

#include "fixtures.hpp"
#include "hsv_aux.hpp"
#include "utils/matrix.hpp"
#include "utils/print.hpp"
#include <opencv2/highgui/highgui.hpp>

#define argc boost::unit_test::framework::master_test_suite().argc
#define argv boost::unit_test::framework::master_test_suite().argv

#define display(TITLE, IMAGE) \
    do { \
        cv::namedWindow((TITLE), CV_WINDOW_NORMAL | CV_WINDOW_KEEPRATIO | CV_GUI_EXPANDED); \
        cv::imshow((TITLE),(IMAGE)); \
    } while(0)

BOOST_AUTO_TEST_CASE(test_ind2sub) {
    const arma::ivec3 size = {3,2,2};

    std::vector<std::pair<arma::ivec3,int>> values = {
        std::make_pair(arma::ivec3{0,0,0}, 0),
        std::make_pair(arma::ivec3{2,0,0}, 2),
        std::make_pair(arma::ivec3{1,1,0}, 4),
        std::make_pair(arma::ivec3{2,0,1}, 8),
        std::make_pair(arma::ivec3{2,1,1}, 11),
    };

    for (auto p: values) {
        BOOST_CHECK(test::equals(p.first, vis::ind2sub(size, p.second)));
    }
}

cv::Mat swapChannels(const cv::Mat& in) {
    cv::Mat out(in.size(), in.type());
    const static int fromto[] = { 0,2,  1,1,  2,0 };
    cv::mixChannels(&in, 1, &out, 1, fromto, 3);
    return out;
}

BOOST_FIXTURE_TEST_CASE(test_functions, test::Peppers) {
    cv::Mat hsv = vis::toHsv(image);

    BOOST_CHECK_EQUAL(hsv.size(), image.size());
    BOOST_CHECK_EQUAL(hsv.type(), image.type());
    BOOST_CHECK(test::hasMinMax(hsv, 0., 1.));

    arma::ivec3 levels = { 3, 2+1, 2+1 };
    cv::Mat quantized = vis::quantize(hsv, levels);
    BOOST_CHECK_EQUAL(quantized.size(), image.size());
    BOOST_CHECK_EQUAL(quantized.type(), image.type());

    std::vector<cv::Mat> planes;
    cv::split(quantized, planes);
    BOOST_CHECK(test::hasMinMax(planes[0], 1, levels[0]));
    BOOST_CHECK(test::hasMinMax(planes[1], 1, levels[1]));
    BOOST_CHECK(test::hasMinMax(planes[2], 1, levels[2]));

    if (argc > 1) {
        display("image", image);
        display("hsv", swapChannels(hsv)); // HSV channels are interpreted as BGR

        planes[0] /= levels[0];
        planes[1] /= levels[1];
        planes[2] /= levels[2];
        cv::merge(planes, quantized);
        display("quantized", swapChannels(quantized)); // idem

        cv::Mat bgr = vis::toBgr(quantized);
        display("rgb", bgr);

        println("Press a key to continue");
        cv::waitKey(0);
    }
}

BOOST_AUTO_TEST_CASE(test_imquantize) {
    cv::Mat data = (cv::Mat_<float>(5,5) << 17, 23,  4, 10, 11,
                                          24,  5,  6, 12, 18,
                                           1,  7, 13, 19, 25,
                                           8, 14, 20, 21,  2,
                                          15, 16, 22,  3,  9);

    arma::fvec thresholds = { 1, 6, 11, 16, 21 };

    cv::Mat expected = (cv::Mat_<float>(5,5) << 5, 6, 1, 3, 4,
                                              6, 2, 3, 4, 4,
                                              2, 2, 4, 5, 6,
                                              3, 4, 5, 5, 2,
                                              3, 5, 6, 2, 3);

    cv::Mat actual = vis::imquantize(data.t(), thresholds); // NOTE transposed wrt Matlab

    printmat(expected);
    printmat(actual);

    BOOST_CHECK(test::equals(expected, actual));
}

BOOST_AUTO_TEST_CASE(test_medfilt2) {
    cv::Mat data = (cv::Mat_<float>(5,5) << 17, 23,  4, 10, 11,
                                            24,  5,  6, 12, 18,
                                             1,  7, 13, 19, 25,
                                             8, 14, 20, 21,  2,
                                            15, 16, 22,  3,  9);

    cv::Mat expected = (cv::Mat_<float>(5,5) << 17, 17,  8,  8, 15,
                                                17,  7,  8, 14, 16,
                                                10, 10, 13, 16, 16,
                                                10, 12, 18, 19,  9,
                                                11, 18, 18,  9,  9);

    cv::Mat actual = vis::medfilt2(data.t()); // NOTE transposed wrt Matlab

    printmat(data);
    printmat(expected);
    printmat(actual);

    BOOST_CHECK(test::equals(expected, actual));
}

BOOST_AUTO_TEST_CASE(test_linspace) {
    {
        arma::fvec expected = {1,2,3,4,5,6,7,8,9,10};
        arma::fvec actual = arma::linspace<arma::fvec>(1., 10., 10);
        BOOST_CHECK(test::equals(expected, actual));
    }
    {
        arma::vec expected = { 1.0, 1.642857143, 2.285714286, 2.928571429, 3.571428571,
                               4.214285714, 4.857142857, 5.5, 6.142857143, 6.785714286,
                               7.428571429, 8.071428571, 8.714285714, 9.357142857, 10.0 };
        arma::vec actual = arma::linspace<arma::vec>(1, 10, 15);
        BOOST_REQUIRE_EQUAL(expected.size(), actual.size());
        for(int i = 0; i < 15; ++i) BOOST_CHECK_CLOSE(expected(i), actual(i), 0.000001);
    }
}

template <typename T>
void doReshapeTest(const arma::Mat<T>& expected, const arma::Mat<T>& actual) {
    printmat(expected);
    printmat(actual);

    BOOST_CHECK_EQUAL(actual.size(), expected.size());
    BOOST_CHECK_EQUAL(actual.n_rows, expected.n_rows);
    BOOST_CHECK_EQUAL(actual.n_cols, expected.n_cols);
    BOOST_CHECK(test::equals(expected, actual));
}

BOOST_AUTO_TEST_CASE(test_reshape) {
    arma::imat data = { 8, 1, 6, 2,
                        3, 5, 7, 9,
                        4, 9, 2, 1 };
    data = arma::reshape(data,4,3).t(); // NOTE column-major vs row-major
    printmat(data);

    {
        arma::imat expected = { 8, 4, 5, 6, 2, 9,
                                3, 1, 9, 7, 2, 1 };
        expected = arma::reshape(expected,6,2).t();

        arma::imat actual(data);
        actual.reshape(2,6);
        doReshapeTest(expected, actual);
    }
    {
        arma::imat expected = { 8, 6,
                                3, 7,
                                4, 2,
                                1, 2,
                                5, 9,
                                9, 1 };
        expected = arma::reshape(expected,2,6).t();

        arma::imat actual(data);
        actual.reshape(6,2);
        doReshapeTest(expected, actual);
    }
}

<commit_msg>Deleted tests for removed functions<commit_after>/**
 * @file test_hsv_aux.cpp
 * @brief Test for HSV color histogram auxiliary functions
 * @author Paolo D'Apice
 */

#define BOOST_TEST_MODULE hsv_aux
#include <boost/test/unit_test.hpp>

#include "fixtures.hpp"
#include "hsv_aux.hpp"
#include "utils/matrix.hpp"
#include "utils/print.hpp"
#include <opencv2/highgui/highgui.hpp>

#define argc boost::unit_test::framework::master_test_suite().argc
#define argv boost::unit_test::framework::master_test_suite().argv

#define display(TITLE, IMAGE) \
    do { \
        cv::namedWindow((TITLE), CV_WINDOW_NORMAL | CV_WINDOW_KEEPRATIO | CV_GUI_EXPANDED); \
        cv::imshow((TITLE),(IMAGE)); \
    } while(0)

BOOST_AUTO_TEST_CASE(test_ind2sub) {
    const arma::ivec3 size = {3,2,2};

    std::vector<std::pair<arma::ivec3,int>> values = {
        std::make_pair(arma::ivec3{0,0,0}, 0),
        std::make_pair(arma::ivec3{2,0,0}, 2),
        std::make_pair(arma::ivec3{1,1,0}, 4),
        std::make_pair(arma::ivec3{2,0,1}, 8),
        std::make_pair(arma::ivec3{2,1,1}, 11),
    };

    for (auto p: values) {
        BOOST_CHECK(test::equals(p.first, vis::ind2sub(size, p.second)));
    }
}

cv::Mat swapChannels(const cv::Mat& in) {
    cv::Mat out(in.size(), in.type());
    const static int fromto[] = { 0,2,  1,1,  2,0 };
    cv::mixChannels(&in, 1, &out, 1, fromto, 3);
    return out;
}

BOOST_FIXTURE_TEST_CASE(test_functions, test::Peppers) {
    cv::Mat hsv = vis::toHsv(image);

    BOOST_CHECK_EQUAL(hsv.size(), image.size());
    BOOST_CHECK_EQUAL(hsv.type(), image.type());
    BOOST_CHECK(test::hasMinMax(hsv, 0., 1.));

    arma::ivec3 levels = { 3, 2+1, 2+1 };
    cv::Mat quantized = vis::quantize(hsv, levels);
    BOOST_CHECK_EQUAL(quantized.size(), image.size());
    BOOST_CHECK_EQUAL(quantized.type(), image.type());

    std::vector<cv::Mat> planes;
    cv::split(quantized, planes);
    BOOST_CHECK(test::hasMinMax(planes[0], 1, levels[0]));
    BOOST_CHECK(test::hasMinMax(planes[1], 1, levels[1]));
    BOOST_CHECK(test::hasMinMax(planes[2], 1, levels[2]));

    if (argc > 1) {
        display("image", image);
        display("hsv", swapChannels(hsv)); // HSV channels are interpreted as BGR

        planes[0] /= levels[0];
        planes[1] /= levels[1];
        planes[2] /= levels[2];
        cv::merge(planes, quantized);
        display("quantized", swapChannels(quantized)); // idem

        cv::Mat bgr = vis::toBgr(quantized);
        display("rgb", bgr);

        println("Press a key to continue");
        cv::waitKey(0);
    }
}

BOOST_AUTO_TEST_CASE(test_imquantize) {
    cv::Mat data = (cv::Mat_<float>(5,5) << 17, 23,  4, 10, 11,
                                          24,  5,  6, 12, 18,
                                           1,  7, 13, 19, 25,
                                           8, 14, 20, 21,  2,
                                          15, 16, 22,  3,  9);

    arma::fvec thresholds = { 1, 6, 11, 16, 21 };

    cv::Mat expected = (cv::Mat_<float>(5,5) << 5, 6, 1, 3, 4,
                                              6, 2, 3, 4, 4,
                                              2, 2, 4, 5, 6,
                                              3, 4, 5, 5, 2,
                                              3, 5, 6, 2, 3);

    cv::Mat actual = vis::imquantize(data.t(), thresholds); // NOTE transposed wrt Matlab

    printmat(expected);
    printmat(actual);

    BOOST_CHECK(test::equals(expected, actual));
}

BOOST_AUTO_TEST_CASE(test_medfilt2) {
    cv::Mat data = (cv::Mat_<float>(5,5) << 17, 23,  4, 10, 11,
                                            24,  5,  6, 12, 18,
                                             1,  7, 13, 19, 25,
                                             8, 14, 20, 21,  2,
                                            15, 16, 22,  3,  9);

    cv::Mat expected = (cv::Mat_<float>(5,5) << 17, 17,  8,  8, 15,
                                                17,  7,  8, 14, 16,
                                                10, 10, 13, 16, 16,
                                                10, 12, 18, 19,  9,
                                                11, 18, 18,  9,  9);

    cv::Mat actual = vis::medfilt2(data.t()); // NOTE transposed wrt Matlab

    printmat(data);
    printmat(expected);
    printmat(actual);

    BOOST_CHECK(test::equals(expected, actual));
}

<|endoftext|>