<commit_before>#include "catch.hpp"
#include "stream.hpp"
#include "gsl.h"
#include <sstream>
#include <algorithm>

using namespace std;
using namespace gsl;

using Payload = vector<ubyte>;
struct TestConnection {
    void newMessage(span<const ubyte> bytes) {
        switch(getMessageType(bytes)) {
        case MqttType::CONNACK:
            connected = true;
            connectionCode = MqttConnack::Code::ACCEPTED;
            break;

        case MqttType::PUBLISH:
            {
                Decerealiser dec{bytes};
                const auto hdr = dec.create<MqttFixedHeader>();
                dec.reset();
                const auto msg = dec.create<MqttPublish>(hdr);
                payloads.emplace_back(msg.payload.begin(), msg.payload.end());
            }
            break;
        default:
            break;
        }

        lastMsg = Payload(bytes.begin(), bytes.end());
    }

    void disconnect() {
        connected = false;
    }

    bool connected{false};
    MqttConnack::Code connectionCode{MqttConnack::Code::NO_AUTH};
    vector<Payload> payloads;
    Payload lastMsg;
};

static vector<ubyte> subscribeMsg(const std::string& topic, ushort msgId) {
    vector<ubyte> msg{0x8b}; //fixed header sans remaining length
    const auto remainingLength = topic.size() + 2 /*topic len*/ + 2 /*msgId*/ + 1 /*qos*/;
    msg.emplace_back(remainingLength);

    msg.emplace_back(msgId >> 8);
    msg.emplace_back(msgId & 0xff);

    msg.emplace_back(topic.size() >> 8);
    msg.emplace_back(topic.size() & 0xff);
    copy(topic.cbegin(), topic.cend(), back_inserter(msg));

    msg.emplace_back(0); //qos

    return msg;
}

int readInto(MqttStream& stream, span<const ubyte> bytes) {
    copy(bytes.cbegin(), bytes.cend(), stream.begin());
    return bytes.size();
}

TEST_CASE("MQTT in 2 packets") {
    MqttServer<TestConnection> server;
    TestConnection connection;
    MqttStream stream{128};

    const auto subscribe = subscribeMsg("top", 33);
    server.newMessage(connection, subscribe);

    const vector<ubyte> bytes1{
        0x3c, 15, //fixed header
        0x00, 0x03, 't', 'o', 'p', //topic name
        0x00, 0x21, //message ID
        1, 2, 3 //first part of payload
    };

    const auto numBytes1 = readInto(stream, bytes1);
    stream.handleMessages(numBytes1, server, connection);
    REQUIRE(connection.payloads == vector<Payload>{});

    const vector<ubyte> bytes2{4, 5, 6, 7, 8}; //2nd part of payload
    const auto numBytes2 = readInto(stream, bytes2);
    stream.handleMessages(numBytes2, server, connection);
    REQUIRE(connection.payloads == (vector<Payload>{{1, 2, 3, 4, 5, 6, 7, 8}}));
}
<commit_msg>2nd passing UT for stream<commit_after>#include "catch.hpp"
#include "stream.hpp"
#include "gsl.h"
#include <sstream>
#include <algorithm>

using namespace std;
using namespace gsl;

using Payload = vector<ubyte>;
struct TestConnection {
    void newMessage(span<const ubyte> bytes) {
        switch(getMessageType(bytes)) {
        case MqttType::CONNACK:
            connected = true;
            connectionCode = MqttConnack::Code::ACCEPTED;
            break;

        case MqttType::PUBLISH:
            {
                Decerealiser dec{bytes};
                const auto hdr = dec.create<MqttFixedHeader>();
                dec.reset();
                const auto msg = dec.create<MqttPublish>(hdr);
                payloads.emplace_back(msg.payload.begin(), msg.payload.end());
            }
            break;
        default:
            break;
        }

        lastMsg = Payload(bytes.begin(), bytes.end());
    }

    void disconnect() {
        connected = false;
    }

    bool connected{false};
    MqttConnack::Code connectionCode{MqttConnack::Code::NO_AUTH};
    vector<Payload> payloads;
    Payload lastMsg;
};

static vector<ubyte> subscribeMsg(const std::string& topic, ushort msgId) {
    vector<ubyte> msg{0x8b}; //fixed header sans remaining length
    const auto remainingLength = topic.size() + 2 /*topic len*/ + 2 /*msgId*/ + 1 /*qos*/;
    msg.emplace_back(remainingLength);

    msg.emplace_back(msgId >> 8);
    msg.emplace_back(msgId & 0xff);

    msg.emplace_back(topic.size() >> 8);
    msg.emplace_back(topic.size() & 0xff);
    copy(topic.cbegin(), topic.cend(), back_inserter(msg));

    msg.emplace_back(0); //qos

    return msg;
}

int readInto(MqttStream& stream, span<const ubyte> bytes) {
    copy(bytes.cbegin(), bytes.cend(), stream.begin());
    return bytes.size();
}

TEST_CASE("MQTT in 2 packets") {
    MqttServer<TestConnection> server;
    TestConnection connection;
    MqttStream stream{128};

    const auto subscribe = subscribeMsg("top", 33);
    server.newMessage(connection, subscribe);

    const vector<ubyte> bytes1{
        0x3c, 15, //fixed header
        0x00, 0x03, 't', 'o', 'p', //topic name
        0x00, 0x21, //message ID
        1, 2, 3 //first part of payload
    };
    const vector<ubyte> bytes2{4, 5, 6, 7, 8}; //2nd part of payload

    const auto numBytes1 = readInto(stream, bytes1);
    stream.handleMessages(numBytes1, server, connection);
    REQUIRE(connection.payloads == vector<Payload>{});

    const auto numBytes2 = readInto(stream, bytes2);
    stream.handleMessages(numBytes2, server, connection);
    REQUIRE(connection.payloads == (vector<Payload>{{1, 2, 3, 4, 5, 6, 7, 8}}));
}

TEST_CASE("Broken header and two messages") {
    MqttServer<TestConnection> server;
    TestConnection connection;
    MqttStream stream{128};

    connection.connected = true; //easier than sending conneciton packet

    const auto subscribe = subscribeMsg("top", 33);
    server.newMessage(connection, subscribe);

    const vector<ubyte> bytes1{0x3c}; //half of header
    const vector<ubyte> bytes2{
        15, //2nd half of fixed header
        0x00, 0x03, 't', 'o', 'p', //topic name
        0x00, 0x21, //message ID
        1, 2, 3, 4, 5, 6, 7, 8,
        0xe0, 0, //header for disconnect
    };

    const auto numBytes1 = readInto(stream, bytes1);
    stream.handleMessages(numBytes1, server, connection);
    REQUIRE(connection.payloads == vector<Payload>{});
    REQUIRE(connection.connected == true);

    const auto numBytes2 = readInto(stream, bytes2);
    stream.handleMessages(numBytes2, server, connection);
    REQUIRE(connection.payloads == (vector<Payload>{{1, 2, 3, 4, 5, 6, 7, 8}}));
    REQUIRE(connection.connected == false);
}
<|endoftext|>


<commit_before>#include "quadrature/utility/quadrature_utilities.h"

#include <algorithm>
#include <cmath>

#include "quadrature/tests/quadrature_point_mock.h"
#include "quadrature/tests/quadrature_generator_mock.h"
#include "quadrature/tests/quadrature_set_mock.h"
#include "quadrature/tests/ordinate_mock.h"

#include "test_helpers/gmock_wrapper.h"
#include "test_helpers/test_helper_functions.h"

namespace  {

using namespace bart;

template <typename DimensionWrapper>
class QuadratureUtilityTests : public ::testing::Test {
 public:
  static constexpr int dim = DimensionWrapper::value;
};

TYPED_TEST_CASE(QuadratureUtilityTests, bart::testing::AllDimensions);

TYPED_TEST(QuadratureUtilityTests, ReflectAcrossOrigin) {
  constexpr int dim = this->dim;

  std::array<double, dim> position, negative_position;
  auto random_position = btest::RandomVector(dim, -10, 10);
  for (int i = 0; i < dim; ++i) {
    position.at(i) = random_position.at(i);
    negative_position.at(i) = -random_position.at(i);
  }

  quadrature::OrdinateMock<dim> mock_ordinate;

  EXPECT_CALL(mock_ordinate, cartesian_position())
      .WillOnce(::testing::Return(position));

  EXPECT_EQ(quadrature::utility::ReflectAcrossOrigin(mock_ordinate),
            negative_position);

  EXPECT_CALL(mock_ordinate, cartesian_position())
      .WillOnce(::testing::Return(negative_position));

  EXPECT_EQ(quadrature::utility::ReflectAcrossOrigin(mock_ordinate),
            position);
}

TYPED_TEST(QuadratureUtilityTests, GenerateAllPositiveX) {
  const int dim = this->dim;
  const int n_points = 3;
  const int n_quadrants = std::pow(2, dim)/2;

  // Quadrature set to be distributed in positive x
  std::vector<std::pair<quadrature::CartesianPosition<dim>, quadrature::Weight>>
      quadrature_set;

  for (int i = 0; i < n_points; ++i) {
    auto random_position = btest::RandomVector(dim, 1, 10);
    auto random_weight = btest::RandomDouble(0, 2);
    std::array<double, dim> position;
    for (int j = 0; j < dim; ++j)
      position.at(j) = random_position.at(j);
    quadrature_set.emplace_back(quadrature::CartesianPosition<dim>(position),
                                quadrature::Weight(random_weight));
  }

  auto distributed_set = quadrature::utility::GenerateAllPositiveX<dim>(quadrature_set);

  EXPECT_EQ(distributed_set.size(), n_points * n_quadrants);

  for (const auto& quadrature_pair : quadrature_set) {
    EXPECT_EQ(1, std::count(distributed_set.cbegin(), distributed_set.cend(),
                            quadrature_pair));
    if (dim > 1) {
      auto negative_y_pair = quadrature_pair;
      negative_y_pair.first.get().at(1) *= -1;
      EXPECT_EQ(1, std::count(distributed_set.cbegin(), distributed_set.cend(),
                              negative_y_pair));
    }
    if (dim > 2) {
      auto negative_z_pair = quadrature_pair;

      negative_z_pair.first.get().at(2) *= -1;
      EXPECT_EQ(1, std::count(distributed_set.cbegin(), distributed_set.cend(),
                              negative_z_pair));
      auto negative_zy_pair = negative_z_pair;
      negative_zy_pair.first.get().at(1) *= -1;
      EXPECT_EQ(1, std::count(distributed_set.cbegin(), distributed_set.cend(),
                              negative_zy_pair));

    }
  }
}

TYPED_TEST(QuadratureUtilityTests, GenerateAllPositiveXScalar) {
  const int dim = this->dim;

  std::vector<std::pair<quadrature::CartesianPosition<dim>, quadrature::Weight>>
      quadrature_set;

  std::array<double, dim> zero_position;
  zero_position.fill(0);

  quadrature_set.emplace_back(quadrature::CartesianPosition<dim>(zero_position),
                              quadrature::Weight(1));

  auto distributed_set =
      quadrature::utility::GenerateAllPositiveX<dim>(quadrature_set);

  EXPECT_EQ(distributed_set.size(), 1);

  EXPECT_EQ(quadrature_set.at(0), distributed_set.at(0));
}

TYPED_TEST(QuadratureUtilityTests, QuadraturePointCompare) {
  const int dim = this->dim;

  std::array<double, dim> position_1, position_2;

  auto random_position_1 = btest::RandomVector(dim, -100, 100);
  auto random_position_2 = btest::RandomVector(dim, -100, 100);

  for (int i = 0; i < dim; ++i) {
    position_1.at(i) = random_position_1.at(i);
    position_2.at(i) = random_position_2.at(i);
  }

  bool expected_result = (position_1 < position_2);

  auto mock_point_1 = std::make_shared<quadrature::QuadraturePointMock<dim>>();
  auto mock_point_2 = std::make_shared<quadrature::QuadraturePointMock<dim>>();

  EXPECT_CALL(*mock_point_1, cartesian_position())
      .WillOnce(::testing::Return(position_1));
  EXPECT_CALL(*mock_point_2, cartesian_position())
      .WillOnce(::testing::Return(position_2));

  quadrature::utility::quadrature_point_compare<dim> compare_struct;

  auto result = compare_struct(mock_point_1, mock_point_2);
  EXPECT_EQ(result, expected_result);

  const auto& const_compare_struct = compare_struct;

  EXPECT_CALL(*mock_point_1, cartesian_position())
      .WillOnce(::testing::Return(position_1));
  EXPECT_CALL(*mock_point_2, cartesian_position())
      .WillOnce(::testing::Return(position_2));

  auto const_result = const_compare_struct(mock_point_1, mock_point_2);
  EXPECT_EQ(const_result, expected_result);
}

} // namespace<commit_msg>added documentation to tests for quadrature utilities<commit_after>#include "quadrature/utility/quadrature_utilities.h"

#include <algorithm>
#include <cmath>

#include "quadrature/tests/quadrature_point_mock.h"
#include "quadrature/tests/quadrature_generator_mock.h"
#include "quadrature/tests/quadrature_set_mock.h"
#include "quadrature/tests/ordinate_mock.h"
#include "test_helpers/gmock_wrapper.h"
#include "test_helpers/test_helper_functions.h"

namespace  {

using namespace bart;

/* Tests for various quadrature utilities. Will be run in all three dimensions.
 */
template <typename DimensionWrapper>
class QuadratureUtilityTests : public ::testing::Test {
 public:
  static constexpr int dim = DimensionWrapper::value;
};

TYPED_TEST_CASE(QuadratureUtilityTests, bart::testing::AllDimensions);

// ReflectAcrossOrigin should return the correct reflected value
TYPED_TEST(QuadratureUtilityTests, ReflectAcrossOrigin) {
  constexpr int dim = this->dim;
  std::array<double, dim> position, negative_position;
  auto random_position = btest::RandomVector(dim, -10, 10);

  for (int i = 0; i < dim; ++i) {
    position.at(i) = random_position.at(i);
    negative_position.at(i) = -random_position.at(i);
  }

  quadrature::OrdinateMock<dim> mock_ordinate;
  EXPECT_CALL(mock_ordinate, cartesian_position())
      .WillOnce(::testing::Return(position));
  EXPECT_EQ(quadrature::utility::ReflectAcrossOrigin(mock_ordinate),
            negative_position);

  EXPECT_CALL(mock_ordinate, cartesian_position())
      .WillOnce(::testing::Return(negative_position));
  EXPECT_EQ(quadrature::utility::ReflectAcrossOrigin(mock_ordinate),
            position);
}

// GenerateAllPositiveX should generate all correct points
TYPED_TEST(QuadratureUtilityTests, GenerateAllPositiveX) {
  const int dim = this->dim;
  const int n_points = 3;
  const int n_quadrants = std::pow(2, dim)/2;

  std::vector<std::pair<quadrature::CartesianPosition<dim>, quadrature::Weight>>
      quadrature_set;

  // Fill the quadrature set with random positions
  for (int i = 0; i < n_points; ++i) {
    auto random_position = btest::RandomVector(dim, 1, 10);
    auto random_weight = btest::RandomDouble(0, 2);
    std::array<double, dim> position;
    for (int j = 0; j < dim; ++j)
      position.at(j) = random_position.at(j);
    quadrature_set.emplace_back(quadrature::CartesianPosition<dim>(position),
                                quadrature::Weight(random_weight));
  }

  auto distributed_set = quadrature::utility::GenerateAllPositiveX<dim>(quadrature_set);

  EXPECT_EQ(distributed_set.size(), n_points * n_quadrants);

  for (const auto& quadrature_pair : quadrature_set) {
    EXPECT_EQ(1, std::count(distributed_set.cbegin(), distributed_set.cend(),
                            quadrature_pair));
    if (dim > 1) {
      auto negative_y_pair = quadrature_pair;
      negative_y_pair.first.get().at(1) *= -1;
      EXPECT_EQ(1, std::count(distributed_set.cbegin(), distributed_set.cend(),
                              negative_y_pair));
    }
    if (dim > 2) {
      auto negative_z_pair = quadrature_pair;

      negative_z_pair.first.get().at(2) *= -1;
      EXPECT_EQ(1, std::count(distributed_set.cbegin(), distributed_set.cend(),
                              negative_z_pair));
      auto negative_zy_pair = negative_z_pair;
      negative_zy_pair.first.get().at(1) *= -1;
      EXPECT_EQ(1, std::count(distributed_set.cbegin(), distributed_set.cend(),
                              negative_zy_pair));

    }
  }
}

/* GenerateAllPositiveXScalar shouldn't have any effect on quadrature points
 * at the origin (the only points without a reflection) */
TYPED_TEST(QuadratureUtilityTests, GenerateAllPositiveXScalar) {
  const int dim = this->dim;

  std::vector<std::pair<quadrature::CartesianPosition<dim>, quadrature::Weight>>
      quadrature_set;
  std::array<double, dim> zero_position;
  zero_position.fill(0);
  quadrature_set.emplace_back(quadrature::CartesianPosition<dim>(zero_position),
                              quadrature::Weight(1));

  auto distributed_set =
      quadrature::utility::GenerateAllPositiveX<dim>(quadrature_set);

  EXPECT_EQ(distributed_set.size(), 1);
  EXPECT_EQ(quadrature_set.at(0), distributed_set.at(0));
}

// QuadraturePointCompare should provide a correct less-than operation.
TYPED_TEST(QuadratureUtilityTests, QuadraturePointCompare) {
  const int dim = this->dim;

  std::array<double, dim> position_1, position_2;
  auto random_position_1 = btest::RandomVector(dim, -100, 100);
  auto random_position_2 = btest::RandomVector(dim, -100, 100);

  for (int i = 0; i < dim; ++i) {
    position_1.at(i) = random_position_1.at(i);
    position_2.at(i) = random_position_2.at(i);
  }

  bool expected_result = (position_1 < position_2);
  auto mock_point_1 = std::make_shared<quadrature::QuadraturePointMock<dim>>();
  auto mock_point_2 = std::make_shared<quadrature::QuadraturePointMock<dim>>();

  EXPECT_CALL(*mock_point_1, cartesian_position())
      .WillOnce(::testing::Return(position_1));
  EXPECT_CALL(*mock_point_2, cartesian_position())
      .WillOnce(::testing::Return(position_2));

  quadrature::utility::quadrature_point_compare<dim> compare_struct;
  auto result = compare_struct(mock_point_1, mock_point_2);
  EXPECT_EQ(result, expected_result);

  // Check const operations
  const auto& const_compare_struct = compare_struct;
  EXPECT_CALL(*mock_point_1, cartesian_position())
      .WillOnce(::testing::Return(position_1));
  EXPECT_CALL(*mock_point_2, cartesian_position())
      .WillOnce(::testing::Return(position_2));

  auto const_result = const_compare_struct(mock_point_1, mock_point_2);
  EXPECT_EQ(const_result, expected_result);
}

} // namespace<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: dynamicregister.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: vg $ $Date: 2003-04-01 13:16:35 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "dynamicregister.hxx"
#ifndef _OSL_PROCESS_H_
#include <osl/process.h>
#endif
// #include <osl/mutex.hxx>
#include <rtl/string.hxx>
#include <rtl/ustring.hxx>
#include "filehelper.hxx"

// -----------------------------------------------------------------------------

DynamicLibraryHelper::DynamicLibraryHelper(rtl::OUString const& _sDLLName, GetOpt & _aOptions)
        :m_pModule(new ::osl::Module()),
         m_suDLLName(_sDLLName),
         m_aOptions(_aOptions)
{
    // create and load the module (shared library)
    rtl::OUString suFile = FileHelper::convertPath( _sDLLName );
    rtl::OString sDLLName = rtl::OUStringToOString(suFile, RTL_TEXTENCODING_ASCII_US);
    if (_aOptions.hasOpt("-verbose"))
    {
        fprintf(stderr, "Try to load '%s'.\n", sDLLName.getStr());
    }

    if (! m_pModule->load( suFile ))
    {
        rtl::OString sDLLName = rtl::OUStringToOString(_sDLLName, RTL_TEXTENCODING_ASCII_US);
        fprintf(stderr, "warning: Can't load module '%s'.\n", sDLLName.getStr());
    }
}

DynamicLibraryHelper::~DynamicLibraryHelper()
{
    delete m_pModule;
}

<commit_msg>INTEGRATION: CWS fwk01ea (1.4.54); FILE MERGED 2004/04/08 12:45:31 sb 1.4.54.1: #116269# Always call osl::Module::load with GLOBAL (otherwise, C++ exception handling fails on Linux).<commit_after>/*************************************************************************
 *
 *  $RCSfile: dynamicregister.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2004-09-20 11:49:15 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "dynamicregister.hxx"
#ifndef _OSL_PROCESS_H_
#include <osl/process.h>
#endif
// #include <osl/mutex.hxx>
#include <rtl/string.hxx>
#include <rtl/ustring.hxx>
#include "filehelper.hxx"

// -----------------------------------------------------------------------------

DynamicLibraryHelper::DynamicLibraryHelper(rtl::OUString const& _sDLLName, GetOpt & _aOptions)
        :m_pModule(new ::osl::Module()),
         m_suDLLName(_sDLLName),
         m_aOptions(_aOptions)
{
    // create and load the module (shared library)
    rtl::OUString suFile = FileHelper::convertPath( _sDLLName );
    rtl::OString sDLLName = rtl::OUStringToOString(suFile, RTL_TEXTENCODING_ASCII_US);
    if (_aOptions.hasOpt("-verbose"))
    {
        fprintf(stderr, "Try to load '%s'.\n", sDLLName.getStr());
    }

    if (! m_pModule->load(suFile, SAL_LOADMODULE_LAZY | SAL_LOADMODULE_GLOBAL))
    {
        rtl::OString sDLLName = rtl::OUStringToOString(_sDLLName, RTL_TEXTENCODING_ASCII_US);
        fprintf(stderr, "warning: Can't load module '%s'.\n", sDLLName.getStr());
    }
}

DynamicLibraryHelper::~DynamicLibraryHelper()
{
    delete m_pModule;
}

<|endoftext|>


<commit_before>#ifndef SIMDIFY_COMMON
#define SIMDIFY_COMMON

#include "../util/inline.hpp"
#include "../util/type.hpp"
#include "../util/1b.hpp"
#include <cmath>
#include <cstdint>
#include <type_traits>
#include <initializer_list>
#include <algorithm>
#include <array>
#include <utility>
#include <iterator>

#define INL SIMDIFY_FORCE_INLINE

namespace simd {

    //
    // types for overload selection/disambiguation
    //
    struct zero_t {};
    struct all_bits_t {};
    struct abs_mask_t {};
    struct sign_bit_t {};

    //
    // forward declarations
    //
    template <typename T>
    struct horizontal_impl;

    template <typename T>
    struct allocator;

    //
    // SIMD type base class (with derived class as T, CRTP-style)
    //
    template <typename _mm_t, typename _fp_t, typename _bitmask_t, typename T>
    struct simd_base {
        using mm_t = _mm_t;
        using fp_t = _fp_t;
        using bitmask_t = _bitmask_t;

        // type-related sanity checks
        static_assert(sizeof(mm_t) % sizeof(fp_t) == 0, "size of mm_t must be a multiple of the size of fp_t");
        static_assert(sizeof(fp_t) == sizeof(bitmask_t), "size of bitmask_t must match the size of fp_t");
        static_assert(std::is_integral<bitmask_t>::value, "bitmask_t must be an integral type");
        static_assert(std::is_unsigned<bitmask_t>::value, "bitmask_t must be an unsigned type");

        // useful constants and types
        static const auto W = sizeof(mm_t) / sizeof(fp_t);
        using array_t = std::array<fp_t, W>;
        using mask_array_t = std::array<bitmask_t, W>;
        using iterator = typename array_t::iterator;
        using reverse_iterator = typename array_t::reverse_iterator;
        using const_iterator = typename array_t::const_iterator;
        using const_reverse_iterator = typename array_t::const_reverse_iterator;
        using unary_op_t = ptr<const T(const T& in)>;
        using binary_op_t = ptr<const T(const T& l, const T& r)>;
        using horizontal = horizontal_impl<T>;

        // a wrapper to disambiguate construction with bitmask_t and fp_t
        struct mask_t {
            // data
            union {
                float f;
                bitmask_t b;
            };

            // useful bit masks
            static const bitmask_t ZERO_BIT_MASK = 0;
            static const bitmask_t ALL_BITS_MASK = ~ZERO_BIT_MASK;
            static const bitmask_t ABS_BIT_MASK = ALL_BITS_MASK >> 1;
            static const bitmask_t SIGN_BIT_MASK = ~ABS_BIT_MASK;

            // constructors
            INL explicit mask_t() {}
            INL explicit mask_t(bitmask_t r) : b(r) {}
            INL mask_t(zero_t) : b(ZERO_BIT_MASK) {}
            INL mask_t(all_bits_t) : b(ALL_BITS_MASK) {}
            INL mask_t(abs_mask_t) : b(ABS_BIT_MASK) {}
            INL mask_t(sign_bit_t) : b(SIGN_BIT_MASK) {}

            // bitmask_t -- fp_t conversion
            INL static bitmask_t tob(fp_t l) { mask_t m; m.f = l; return m.b; }
            INL static fp_t tof(bitmask_t l) { mask_t m; m.b = l; return m.f; }

            // bitwise operations with fp_t
            INL static fp_t andf(fp_t l, fp_t r) { return tof(tob(l) & tob(r)); }
            INL static fp_t orf(fp_t l, fp_t r) { return tof(tob(l) | tob(r)); }
            INL static fp_t xorf(fp_t l, fp_t r) { return tof(tob(l) ^ tob(r)); }
            INL static fp_t notf(fp_t l) { return tof(~tob(l)); }
            INL static fp_t andnotf(fp_t l, fp_t r) { return tof(tob(l) & ~tob(r)); }
        };

        // data
        union { mm_t mm; array_t f; mask_array_t i; };

        // constructor
        INL simd_base() {}
        INL simd_base(mm_t r) : mm(r) {}
    };

    //
    // helper class for lazy evaluation of bitwise not
    //
    template <typename T>
    struct bitwise_not;

    //
    // meta operations - apply to all SIMD types
    //
    template <typename T> INL T& operator &=(T& l, const T& r) { l = l & r; return l; }
    template <typename T> INL T& operator |=(T& l, const T& r) { l = l | r; return l; }
    template <typename T> INL T& operator ^=(T& l, const T& r) { l = l ^ r; return l; }
    template <typename T> INL T& operator +=(T& l, const T& r) { l = l + r; return l; }
    template <typename T> INL T& operator -=(T& l, const T& r) { l = l - r; return l; }
    template <typename T> INL T& operator *=(T& l, const T& r) { l = l * r; return l; }
    template <typename T> INL T& operator /=(T& l, const T& r) { l = l / r; return l; }
    template <typename T> INL const T abs(const T& in) { return in & T(ABS_MASK); }
    template <typename T> INL const T signbit(const T& in) { return in & T(SIGN_BIT); }
    template <typename T> INL const T signum(const T& in) { return cond(in > T(0), T(1), T(-1)); }

    template<typename T>
    INL const T operator~(const bitwise_not<T>& l) { return l.neg; }
    template<typename T>
    INL const T operator&(const bitwise_not<T>& l, const T& r) { return andnot(l.neg, r); }
    template<typename T>
    INL const T operator&(const T& l, const bitwise_not<T>& r) { return andnot(r.neg, l); }
    template<typename T>
    INL const bitwise_not<T> operator&(const bitwise_not<T>& l, const bitwise_not<T>& r) { return bitwise_not<T>(l.neg | r.neg); }
    template<typename T>
    INL const bitwise_not<T> operator|(const bitwise_not<T>& l, const bitwise_not<T>& r) { return bitwise_not<T>(l.neg & r.neg); }
    template<typename T>
    INL const T operator^(const bitwise_not<T>& l, const bitwise_not<T>& r) { return l.neg ^ r.neg; }

    template <typename T>
    INL const T apply_mask(const T& in, const T& mask, zero_t) {
        return cond(mask, in, T(zero_t{}));
    }
    template <typename T>
    INL const T apply_mask(const T& in, const T& mask, typename T::fp_t neutral_value) {
        return cond(mask, in, T(neutral_value));
    }
    template <typename T>
    INL const T apply_mask(const T& in, const T& mask, typename T::mask_t neutral_mask) {
        return cond(mask, in, T(neutral_mask));
    }
    template <typename T>
    INL const T apply_mask(const T& in, const T& mask, const T& neutral_value_vector) {
        return cond(mask, in, neutral_value_vector);
    }

    //
    // provides access to min, max, operator+, operator* before they have been declared
    //
    template <typename T>
    struct operators {
        static INL const T min_(const T& l, const T& r) { return min(l, r); }
        static INL const T max_(const T& l, const T& r) { return max(l, r); }
        static INL const T add_(const T& l, const T& r) { return l + r; }
        static INL const T mul_(const T& l, const T& r) { return l * r; }
    };

    //
    // base class for horizontal<T>
    //
    template <typename T>
    struct horizontal_impl_base {
        using unary_op_t = ptr<const T(const T& in)>;
        using binary_op_t = ptr<const T(const T& l, const T& r)>;
        using fp_t = typename T::fp_t;
        using reduce_find_t = std::pair<fp_t, uint>;
        using ops = operators<T>;

        template <binary_op_t F>
        static INL fp_t reduce(const T& in) { return reduce_vector<F>(in).front(); }

        template <binary_op_t F>
        static INL const T reduce_vector(const T& in) { return horizontal_impl<T>::template reduce_vector<F>(in); }

        template <binary_op_t F>
        static INL reduce_find_t reduce_find(const T& in) {
            auto in_reduced = reduce_vector<F>(in);
            auto selected = horizontal_impl<T>::find(in == in_reduced);
            return std::make_pair(in_reduced.front(), selected);
        }

        template <binary_op_t F, typename N>
        static INL fp_t reduce_with_mask(const T& in, const T& mask, N&& neutral_value) {
            return reduce<F>(apply_mask(in, mask, std::forward<N>(neutral_value)));
        }

        template <binary_op_t F, typename N>
        static INL reduce_find_t reduce_find_with_mask(const T& in, const T& mask, N&& neutral_value) {
            return reduce_find<F>(apply_mask(in, mask, std::forward<N>(neutral_value)));
        }

        static INL fp_t min(const T& in) { return reduce<ops::min_>(in); }
        static INL fp_t max(const T& in) { return reduce<ops::max_>(in); }
        static INL fp_t sum(const T& in) { return reduce<ops::add_>(in); }
        static INL fp_t product(const T& in) { return reduce<ops::mul_>(in); }
        static INL reduce_find_t min_find(const T& in) { return reduce_find<ops::min_>(in); }
        static INL reduce_find_t max_find(const T& in) { return reduce_find<ops::max_>(in); }

        static INL fp_t min_with_mask(const T& in, const T& mask) {
            return reduce_with_mask<ops::min_>(in, mask, std::numeric_limits<fp_t>::max());
        }
        static INL fp_t max_with_mask(const T& in, const T& mask) {
            return reduce_with_mask<ops::max_>(in, mask, std::numeric_limits<fp_t>::min());
        }
        static INL fp_t sum_with_mask(const T& in, const T& mask) {
            return reduce_with_mask<ops::add_>(in, mask, zero_t{});
        }
        static INL fp_t product_with_mask(const T& in, const T& mask) {
            return reduce_with_mask<ops::add_>(in, mask, fp_t(1));
        }
        static INL reduce_find_t min_find_with_mask(const T& in, const T& mask) {
            return reduce_find_with_mask<ops::min_>(in, mask, std::numeric_limits<fp_t>::max());
        }
        static INL reduce_find_t max_find_with_mask(const T& in, const T& mask) {
            return reduce_find_with_mask<ops::max_>(in, mask, std::numeric_limits<fp_t>::min());
        }
    };

}

#undef INL

#endif // SIMDIFY_COMMON
<commit_msg>Clang compiler errors/warnings removal sweep<commit_after>#ifndef SIMDIFY_COMMON
#define SIMDIFY_COMMON

#include "../util/inline.hpp"
#include "../util/type.hpp"
#include "../util/1b.hpp"
#include <cmath>
#include <cstdint>
#include <type_traits>
#include <initializer_list>
#include <algorithm>
#include <array>
#include <utility>
#include <iterator>

#define INL SIMDIFY_FORCE_INLINE

namespace simd {

    //
    // types for overload selection/disambiguation
    //
    struct zero_t {};
    struct all_bits_t {};
    struct abs_mask_t {};
    struct sign_bit_t {};

    //
    // forward declarations
    //
    template <typename T>
    struct horizontal_impl;

    template <typename T>
    struct allocator;

    //
    // SIMD type base class (with derived class as T, CRTP-style)
    //
    template <typename _mm_t, typename _fp_t, typename _bitmask_t, typename T>
    struct simd_base {
        using mm_t = _mm_t;
        using fp_t = _fp_t;
        using bitmask_t = _bitmask_t;

        // type-related sanity checks
        static_assert(sizeof(mm_t) % sizeof(fp_t) == 0, "size of mm_t must be a multiple of the size of fp_t");
        static_assert(sizeof(fp_t) == sizeof(bitmask_t), "size of bitmask_t must match the size of fp_t");
        static_assert(std::is_integral<bitmask_t>::value, "bitmask_t must be an integral type");
        static_assert(std::is_unsigned<bitmask_t>::value, "bitmask_t must be an unsigned type");

        // useful constants and types
        static const auto W = sizeof(mm_t) / sizeof(fp_t);
        using array_t = std::array<fp_t, W>;
        using mask_array_t = std::array<bitmask_t, W>;
        using iterator = typename array_t::iterator;
        using reverse_iterator = typename array_t::reverse_iterator;
        using const_iterator = typename array_t::const_iterator;
        using const_reverse_iterator = typename array_t::const_reverse_iterator;
        using unary_op_t = ptr<const T(const T& in)>;
        using binary_op_t = ptr<const T(const T& l, const T& r)>;
        using horizontal = horizontal_impl<T>;

        // a wrapper to disambiguate construction with bitmask_t and fp_t
        struct mask_t {
            // data
            union {
                float f;
                bitmask_t b;
            };

            // useful bit masks
            static const bitmask_t ZERO_BIT_MASK = 0;
            static const bitmask_t ALL_BITS_MASK = ~ZERO_BIT_MASK;
            static const bitmask_t ABS_BIT_MASK = ALL_BITS_MASK >> 1;
            static const bitmask_t SIGN_BIT_MASK = ~ABS_BIT_MASK;

            // constructors
            INL explicit mask_t() {}
            INL explicit mask_t(bitmask_t r) : b(r) {}
            INL mask_t(zero_t) : b(ZERO_BIT_MASK) {}
            INL mask_t(all_bits_t) : b(ALL_BITS_MASK) {}
            INL mask_t(abs_mask_t) : b(ABS_BIT_MASK) {}
            INL mask_t(sign_bit_t) : b(SIGN_BIT_MASK) {}

            // bitmask_t -- fp_t conversion
            INL static bitmask_t tob(fp_t l) { mask_t m; m.f = l; return m.b; }
            INL static fp_t tof(bitmask_t l) { mask_t m; m.b = l; return m.f; }

            // bitwise operations with fp_t
            INL static fp_t andf(fp_t l, fp_t r) { return tof(tob(l) & tob(r)); }
            INL static fp_t orf(fp_t l, fp_t r) { return tof(tob(l) | tob(r)); }
            INL static fp_t xorf(fp_t l, fp_t r) { return tof(tob(l) ^ tob(r)); }
            INL static fp_t notf(fp_t l) { return tof(~tob(l)); }
            INL static fp_t andnotf(fp_t l, fp_t r) { return tof(tob(l) & ~tob(r)); }
        };

        // data
        union { mm_t mm; array_t f; mask_array_t i; };

        // constructor
        INL simd_base() {}
        INL simd_base(mm_t r) : mm(r) {}
    };

    //
    // helper class for lazy evaluation of bitwise not
    //
    template <typename T>
    struct bitwise_not;

    //
    // meta operations - apply to all SIMD types
    //
    template <typename T> INL T& operator &=(T& l, const T& r) { l = l & r; return l; }
    template <typename T> INL T& operator |=(T& l, const T& r) { l = l | r; return l; }
    template <typename T> INL T& operator ^=(T& l, const T& r) { l = l ^ r; return l; }
    template <typename T> INL T& operator +=(T& l, const T& r) { l = l + r; return l; }
    template <typename T> INL T& operator -=(T& l, const T& r) { l = l - r; return l; }
    template <typename T> INL T& operator *=(T& l, const T& r) { l = l * r; return l; }
    template <typename T> INL T& operator /=(T& l, const T& r) { l = l / r; return l; }
    template <typename T> INL const T abs(const T& in) { return in & T(abs_mask_t{}); }
    template <typename T> INL const T signbit(const T& in) { return in & T(sign_bit_t{}); }
    template <typename T> INL const T signum(const T& in) { return cond(in > T(zero_t{}), T(1), T(-1)); }

    template<typename T>
    INL const T operator~(const bitwise_not<T>& l) { return l.neg; }
    template<typename T>
    INL const T operator&(const bitwise_not<T>& l, const T& r) { return andnot(l.neg, r); }
    template<typename T>
    INL const T operator&(const T& l, const bitwise_not<T>& r) { return andnot(r.neg, l); }
    template<typename T>
    INL const bitwise_not<T> operator&(const bitwise_not<T>& l, const bitwise_not<T>& r) { return bitwise_not<T>(l.neg | r.neg); }
    template<typename T>
    INL const bitwise_not<T> operator|(const bitwise_not<T>& l, const bitwise_not<T>& r) { return bitwise_not<T>(l.neg & r.neg); }
    template<typename T>
    INL const T operator^(const bitwise_not<T>& l, const bitwise_not<T>& r) { return l.neg ^ r.neg; }

    template <typename T>
    INL const T apply_mask(const T& in, const T& mask, zero_t) {
        return cond(mask, in, T(zero_t{}));
    }
    template <typename T>
    INL const T apply_mask(const T& in, const T& mask, typename T::fp_t neutral_value) {
        return cond(mask, in, T(neutral_value));
    }
    template <typename T>
    INL const T apply_mask(const T& in, const T& mask, typename T::mask_t neutral_mask) {
        return cond(mask, in, T(neutral_mask));
    }
    template <typename T>
    INL const T apply_mask(const T& in, const T& mask, const T& neutral_value_vector) {
        return cond(mask, in, neutral_value_vector);
    }

    //
    // provides access to min, max, operator+, operator* before they have been declared
    //
    template <typename T>
    struct operators {
        static INL const T min_(const T& l, const T& r) { return min(l, r); }
        static INL const T max_(const T& l, const T& r) { return max(l, r); }
        static INL const T add_(const T& l, const T& r) { return l + r; }
        static INL const T mul_(const T& l, const T& r) { return l * r; }
    };

    //
    // base class for horizontal<T>
    //
    template <typename T>
    struct horizontal_impl_base {
        using unary_op_t = ptr<const T(const T& in)>;
        using binary_op_t = ptr<const T(const T& l, const T& r)>;
        using fp_t = typename T::fp_t;
        using reduce_find_t = std::pair<fp_t, uint>;
        using ops = operators<T>;

        template <binary_op_t F>
        static INL fp_t reduce(const T& in) { return reduce_vector<F>(in).front(); }

        template <binary_op_t F>
        static INL const T reduce_vector(const T& in) { return horizontal_impl<T>::template reduce_vector<F>(in); }

        template <binary_op_t F>
        static INL reduce_find_t reduce_find(const T& in) {
            auto in_reduced = reduce_vector<F>(in);
            auto selected = horizontal_impl<T>::find(in == in_reduced);
            return std::make_pair(in_reduced.front(), selected);
        }

        template <binary_op_t F, typename N>
        static INL fp_t reduce_with_mask(const T& in, const T& mask, N&& neutral_value) {
            return reduce<F>(apply_mask(in, mask, std::forward<N>(neutral_value)));
        }

        template <binary_op_t F, typename N>
        static INL reduce_find_t reduce_find_with_mask(const T& in, const T& mask, N&& neutral_value) {
            return reduce_find<F>(apply_mask(in, mask, std::forward<N>(neutral_value)));
        }

        static INL fp_t min(const T& in) { return reduce<ops::min_>(in); }
        static INL fp_t max(const T& in) { return reduce<ops::max_>(in); }
        static INL fp_t sum(const T& in) { return reduce<ops::add_>(in); }
        static INL fp_t product(const T& in) { return reduce<ops::mul_>(in); }
        static INL reduce_find_t min_find(const T& in) { return reduce_find<ops::min_>(in); }
        static INL reduce_find_t max_find(const T& in) { return reduce_find<ops::max_>(in); }

        static INL fp_t min_with_mask(const T& in, const T& mask) {
            return reduce_with_mask<ops::min_>(in, mask, std::numeric_limits<fp_t>::max());
        }
        static INL fp_t max_with_mask(const T& in, const T& mask) {
            return reduce_with_mask<ops::max_>(in, mask, std::numeric_limits<fp_t>::min());
        }
        static INL fp_t sum_with_mask(const T& in, const T& mask) {
            return reduce_with_mask<ops::add_>(in, mask, zero_t{});
        }
        static INL fp_t product_with_mask(const T& in, const T& mask) {
            return reduce_with_mask<ops::add_>(in, mask, fp_t(1));
        }
        static INL reduce_find_t min_find_with_mask(const T& in, const T& mask) {
            return reduce_find_with_mask<ops::min_>(in, mask, std::numeric_limits<fp_t>::max());
        }
        static INL reduce_find_t max_find_with_mask(const T& in, const T& mask) {
            return reduce_find_with_mask<ops::max_>(in, mask, std::numeric_limits<fp_t>::min());
        }
    };

}

#undef INL

#endif // SIMDIFY_COMMON
<|endoftext|>


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

#include "environment_capture_stage.hpp"

#include <graphicsBuffer.h>

#include <render_pipeline/rpcore/render_pipeline.hpp>
#include <render_pipeline/rpcore/render_target.hpp>
#include <render_pipeline/rpcore/globals.hpp>
#include <render_pipeline/rpcore/native/tag_state_manager.h>
#include <render_pipeline/rpcore/util/task_scheduler.hpp>

#include "environment_probe.hpp"

namespace rpplugins {

EnvironmentCaptureStage::RequireType EnvironmentCaptureStage::required_inputs = { "DefaultEnvmap", "AllLightsData", "maxLightIndex" };
EnvironmentCaptureStage::RequireType EnvironmentCaptureStage::required_pipes;

EnvironmentCaptureStage::EnvironmentCaptureStage(rpcore::RenderPipeline& pipeline): RenderStage(pipeline, "EnvironmentCaptureStage")
{
    rig_node = rpcore::Globals::render.attach_new_node("EnvmapCamRig");
    _pta_index = PTA_int::empty_array(1);
}

void EnvironmentCaptureStage::create()
{
    _target = create_target("CaptureScene");
    _target->set_size(_resolution * 6, _resolution);
    _target->add_depth_attachment(16);
    _target->add_color_attachment(16, true);
    _target->prepare_render(NodePath());

    // Remove all unused display regions
    GraphicsBuffer* internal_buffer = _target->get_internal_buffer();
    internal_buffer->remove_all_display_regions();
    internal_buffer->disable_clears();
    internal_buffer->get_overlay_display_region()->disable_clears();

    setup_camera_rig();
    create_store_targets();
    create_filter_targets();
}

void EnvironmentCaptureStage::setup_camera_rig()
{
    const LVecBase3f directions[6] = {
        LVecBase3f(1, 0, 0), LVecBase3f(-1, 0, 0), LVecBase3f(0, 1, 0),
        LVecBase3f(0, -1, 0), LVecBase3f(0, 0, 1), LVecBase3f(0, 0, -1),};

    // Prepare the display regions
    for (size_t i = 0; i < std::extent<decltype(directions)>::value; ++i)
    {
        DisplayRegion* region = _target->get_internal_buffer()->make_display_region(
            i / 6.0f, i / 6.0f + 1 / 6.0f, 0.0f, 1.0f);
        region->set_sort(25 + i);
        region->set_active(true);
        region->disable_clears();

        // Set the correct clears
        region->set_clear_depth_active(true);
        region->set_clear_depth(1.0f);
        region->set_clear_color_active(true);
        region->set_clear_color(LColorf(0));

        PT(PerspectiveLens) lens = new PerspectiveLens;
        lens->set_fov(90.0f);
        lens->set_near_far(0.001f, 1.0f);
        PT(Camera) camera = new Camera(std::string("EnvmapCam-") + std::to_string(i), lens);
        NodePath camera_np = rig_node.attach_new_node(camera);
        camera_np.look_at(camera_np, directions[i]);
        region->set_camera(camera_np);
        regions.push_back(region);
        cameras.push_back(camera_np);
    }

    cameras[0].set_r(90);
    cameras[1].set_r(-90);
    cameras[3].set_r(180);
    cameras[5].set_r(180);

    // Register cameras
    for (NodePath& camera_np :cameras)
        pipeline_.get_tag_mgr()->register_camera("envmap", DCAST(Camera, camera_np.node()));
}

void EnvironmentCaptureStage::create_store_targets()
{
    _target_store = create_target("StoreCubemap");
    _target_store->set_size(_resolution * 6, _resolution);
    _target_store->prepare_buffer();
    _target_store->set_shader_input(ShaderInput("SourceTex", _target->get_color_tex()));
    _target_store->set_shader_input(ShaderInput("DestTex", _storage_tex));
    _target_store->set_shader_input(ShaderInput("currentIndex", _pta_index));

    _temporary_diffuse_map = rpcore::Image::create_cube("DiffuseTemp", _resolution, "RGBA16");
    _target_store_diff = create_target("StoreCubemapDiffuse");
    _target_store_diff->set_size(_resolution * 6, _resolution);
    _target_store_diff->prepare_buffer();
    _target_store_diff->set_shader_input(ShaderInput("SourceTex", _target->get_color_tex()));
    _target_store_diff->set_shader_input(ShaderInput("DestTex", _temporary_diffuse_map->get_texture()));
    _target_store_diff->set_shader_input(ShaderInput("currentIndex", _pta_index));
}

void EnvironmentCaptureStage::create_filter_targets()
{
    int mip = 0;
    int size = _resolution;
    while (size > 1)
    {
        size = size / 2;
        mip += 1;
        const std::string string_size(std::to_string(size));
        auto target = create_target(std::string("FilterCubemap:") + std::to_string(mip) + "-" + string_size + "x" + string_size);
        target->set_size(size * 6, size);
        target->prepare_buffer();
        target->set_shader_input(ShaderInput("currentIndex", _pta_index));
        target->set_shader_input(ShaderInput("currentMip", LVecBase4i(mip, 0, 0, 0)));
        target->set_shader_input(ShaderInput("SourceTex", _storage_tex));
        target->set_shader_input(ShaderInput("DestTex", _storage_tex, false, true, -1, mip, 0));
        _filter_targets.push_back(target);
    }

    // Target to filter the diffuse cubemap
    _filter_diffuse_target = create_target("FilterCubemapDiffuse");
    _filter_diffuse_target->set_size(_diffuse_resolution * 6, _diffuse_resolution);
    _filter_diffuse_target->prepare_buffer();
    _filter_diffuse_target->set_shader_input(ShaderInput("SourceTex", _temporary_diffuse_map->get_texture()));
    _filter_diffuse_target->set_shader_input(ShaderInput("DestTex", _storage_tex_diffuse));
    _filter_diffuse_target->set_shader_input(ShaderInput("currentIndex", _pta_index));
}

void EnvironmentCaptureStage::update()
{
    // First, disable all targets
    for (const auto& id_target: get_targets())
        id_target.second->set_active(false);

    // Check for updated faces
    for (size_t i = 0, i_end=regions.size(); i < i_end; ++i)
        if (pipeline_.get_task_scheduler()->is_scheduled(std::string("envprobes_capture_envmap_face") + std::to_string(i)))
            regions[i]->set_active(true);

    // Check for filtering
    if (pipeline_.get_task_scheduler()->is_scheduled("envprobes_filter_and_store_envmap"))
    {
        _target_store->set_active(true);
        _target_store_diff->set_active(true);
        _filter_diffuse_target->set_active(true);

        for (auto&& target: _filter_targets)
            target->set_active(true);
    }
}

void EnvironmentCaptureStage::set_shader_input(const ShaderInput& inp)
{
    rpcore::Globals::render.set_shader_input(inp);
}

void EnvironmentCaptureStage::set_probe(EnvironmentProbe* probe)
{
    rig_node.set_mat(probe->get_matrix());
    _pta_index[0] = probe->get_index();
}

void EnvironmentCaptureStage::reload_shaders()
{
    _target_store->set_shader(load_plugin_shader({"store_cubemap.frag.glsl"}));
    _target_store_diff->set_shader(load_plugin_shader({"store_cubemap_diffuse.frag.glsl"}));
    _filter_diffuse_target->set_shader(load_plugin_shader({"filter_cubemap_diffuse.frag.glsl"}));

    for (size_t i=0, i_end=_filter_targets.size(); i < i_end; ++i)
        _filter_targets[i]->set_shader(load_plugin_shader({std::string("mips/") + std::to_string(i) + ".autogen.glsl"}));
}

std::string EnvironmentCaptureStage::get_plugin_id() const
{
    return RPPLUGIN_ID_STRING;
}

}    // namespace rpplugins
<commit_msg>Fix IESDatasetTex error message<commit_after>/**
 * Render Pipeline C++
 *
 * Copyright (c) 2014-2016 tobspr <tobias.springer1@gmail.com>
 * Copyright (c) 2016-2017 Center of Human-centered Interaction for Coexistence.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
 * and associated documentation files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial
 * portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include "environment_capture_stage.hpp"

#include <graphicsBuffer.h>

#include <render_pipeline/rpcore/render_pipeline.hpp>
#include <render_pipeline/rpcore/render_target.hpp>
#include <render_pipeline/rpcore/globals.hpp>
#include <render_pipeline/rpcore/native/tag_state_manager.h>
#include <render_pipeline/rpcore/util/task_scheduler.hpp>

#include "environment_probe.hpp"

namespace rpplugins {

EnvironmentCaptureStage::RequireType EnvironmentCaptureStage::required_inputs = { "DefaultEnvmap", "AllLightsData", "maxLightIndex", "IESDatasetTex" };
EnvironmentCaptureStage::RequireType EnvironmentCaptureStage::required_pipes;

EnvironmentCaptureStage::EnvironmentCaptureStage(rpcore::RenderPipeline& pipeline): RenderStage(pipeline, "EnvironmentCaptureStage")
{
    rig_node = rpcore::Globals::render.attach_new_node("EnvmapCamRig");
    _pta_index = PTA_int::empty_array(1);
}

void EnvironmentCaptureStage::create()
{
    _target = create_target("CaptureScene");
    _target->set_size(_resolution * 6, _resolution);
    _target->add_depth_attachment(16);
    _target->add_color_attachment(16, true);
    _target->prepare_render(NodePath());

    // Remove all unused display regions
    GraphicsBuffer* internal_buffer = _target->get_internal_buffer();
    internal_buffer->remove_all_display_regions();
    internal_buffer->disable_clears();
    internal_buffer->get_overlay_display_region()->disable_clears();

    setup_camera_rig();
    create_store_targets();
    create_filter_targets();
}

void EnvironmentCaptureStage::setup_camera_rig()
{
    const LVecBase3f directions[6] = {
        LVecBase3f(1, 0, 0), LVecBase3f(-1, 0, 0), LVecBase3f(0, 1, 0),
        LVecBase3f(0, -1, 0), LVecBase3f(0, 0, 1), LVecBase3f(0, 0, -1),};

    // Prepare the display regions
    for (size_t i = 0; i < std::extent<decltype(directions)>::value; ++i)
    {
        DisplayRegion* region = _target->get_internal_buffer()->make_display_region(
            i / 6.0f, i / 6.0f + 1 / 6.0f, 0.0f, 1.0f);
        region->set_sort(25 + i);
        region->set_active(true);
        region->disable_clears();

        // Set the correct clears
        region->set_clear_depth_active(true);
        region->set_clear_depth(1.0f);
        region->set_clear_color_active(true);
        region->set_clear_color(LColorf(0));

        PT(PerspectiveLens) lens = new PerspectiveLens;
        lens->set_fov(90.0f);
        lens->set_near_far(0.001f, 1.0f);
        PT(Camera) camera = new Camera(std::string("EnvmapCam-") + std::to_string(i), lens);
        NodePath camera_np = rig_node.attach_new_node(camera);
        camera_np.look_at(camera_np, directions[i]);
        region->set_camera(camera_np);
        regions.push_back(region);
        cameras.push_back(camera_np);
    }

    cameras[0].set_r(90);
    cameras[1].set_r(-90);
    cameras[3].set_r(180);
    cameras[5].set_r(180);

    // Register cameras
    for (NodePath& camera_np :cameras)
        pipeline_.get_tag_mgr()->register_camera("envmap", DCAST(Camera, camera_np.node()));
}

void EnvironmentCaptureStage::create_store_targets()
{
    _target_store = create_target("StoreCubemap");
    _target_store->set_size(_resolution * 6, _resolution);
    _target_store->prepare_buffer();
    _target_store->set_shader_input(ShaderInput("SourceTex", _target->get_color_tex()));
    _target_store->set_shader_input(ShaderInput("DestTex", _storage_tex));
    _target_store->set_shader_input(ShaderInput("currentIndex", _pta_index));

    _temporary_diffuse_map = rpcore::Image::create_cube("DiffuseTemp", _resolution, "RGBA16");
    _target_store_diff = create_target("StoreCubemapDiffuse");
    _target_store_diff->set_size(_resolution * 6, _resolution);
    _target_store_diff->prepare_buffer();
    _target_store_diff->set_shader_input(ShaderInput("SourceTex", _target->get_color_tex()));
    _target_store_diff->set_shader_input(ShaderInput("DestTex", _temporary_diffuse_map->get_texture()));
    _target_store_diff->set_shader_input(ShaderInput("currentIndex", _pta_index));
}

void EnvironmentCaptureStage::create_filter_targets()
{
    int mip = 0;
    int size = _resolution;
    while (size > 1)
    {
        size = size / 2;
        mip += 1;
        const std::string string_size(std::to_string(size));
        auto target = create_target(std::string("FilterCubemap:") + std::to_string(mip) + "-" + string_size + "x" + string_size);
        target->set_size(size * 6, size);
        target->prepare_buffer();
        target->set_shader_input(ShaderInput("currentIndex", _pta_index));
        target->set_shader_input(ShaderInput("currentMip", LVecBase4i(mip, 0, 0, 0)));
        target->set_shader_input(ShaderInput("SourceTex", _storage_tex));
        target->set_shader_input(ShaderInput("DestTex", _storage_tex, false, true, -1, mip, 0));
        _filter_targets.push_back(target);
    }

    // Target to filter the diffuse cubemap
    _filter_diffuse_target = create_target("FilterCubemapDiffuse");
    _filter_diffuse_target->set_size(_diffuse_resolution * 6, _diffuse_resolution);
    _filter_diffuse_target->prepare_buffer();
    _filter_diffuse_target->set_shader_input(ShaderInput("SourceTex", _temporary_diffuse_map->get_texture()));
    _filter_diffuse_target->set_shader_input(ShaderInput("DestTex", _storage_tex_diffuse));
    _filter_diffuse_target->set_shader_input(ShaderInput("currentIndex", _pta_index));
}

void EnvironmentCaptureStage::update()
{
    // First, disable all targets
    for (const auto& id_target: get_targets())
        id_target.second->set_active(false);

    // Check for updated faces
    for (size_t i = 0, i_end=regions.size(); i < i_end; ++i)
        if (pipeline_.get_task_scheduler()->is_scheduled(std::string("envprobes_capture_envmap_face") + std::to_string(i)))
            regions[i]->set_active(true);

    // Check for filtering
    if (pipeline_.get_task_scheduler()->is_scheduled("envprobes_filter_and_store_envmap"))
    {
        _target_store->set_active(true);
        _target_store_diff->set_active(true);
        _filter_diffuse_target->set_active(true);

        for (auto&& target: _filter_targets)
            target->set_active(true);
    }
}

void EnvironmentCaptureStage::set_shader_input(const ShaderInput& inp)
{
    rpcore::Globals::render.set_shader_input(inp);
}

void EnvironmentCaptureStage::set_probe(EnvironmentProbe* probe)
{
    rig_node.set_mat(probe->get_matrix());
    _pta_index[0] = probe->get_index();
}

void EnvironmentCaptureStage::reload_shaders()
{
    _target_store->set_shader(load_plugin_shader({"store_cubemap.frag.glsl"}));
    _target_store_diff->set_shader(load_plugin_shader({"store_cubemap_diffuse.frag.glsl"}));
    _filter_diffuse_target->set_shader(load_plugin_shader({"filter_cubemap_diffuse.frag.glsl"}));

    for (size_t i=0, i_end=_filter_targets.size(); i < i_end; ++i)
        _filter_targets[i]->set_shader(load_plugin_shader({std::string("mips/") + std::to_string(i) + ".autogen.glsl"}));
}

std::string EnvironmentCaptureStage::get_plugin_id() const
{
    return RPPLUGIN_ID_STRING;
}

}    // namespace rpplugins
<|endoftext|>


<commit_before>#include "sbt.h"

#include <llvm/Bitcode/BitcodeWriter.h>
#include <llvm/MC/MCAsmInfo.h>
#include <llvm/MC/MCContext.h>
#include <llvm/MC/MCDisassembler/MCDisassembler.h>
#include <llvm/MC/MCInstrInfo.h>
#include <llvm/MC/MCObjectFileInfo.h>
#include <llvm/MC/MCRegisterInfo.h>
#include <llvm/Object/Binary.h>
#include <llvm/Object/ObjectFile.h>
#include <llvm/Support/FileSystem.h>
#include <llvm/Support/Signals.h>
#include <llvm/Support/TargetRegistry.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Target/TargetMachine.h>

using namespace llvm;

namespace sbt {

void SBT::init()
{
  BIN_NAME = new std::string("riscv-sbt");

  // print a stack trace if we signal out.
  sys::PrintStackTraceOnErrorSignal(*BIN_NAME);

  InitializeAllTargetInfos();
  InitializeAllTargetMCs();
  InitializeAllAsmParsers();
  InitializeAllDisassemblers();
}

void SBT::finish()
{
  delete BIN_NAME;
  llvm_shutdown();
}

Expected<SBT> SBT::create(
    const llvm::cl::list<std::string> &InputFiles,
    const std::string &OutputFile)
{
  Error Err = Error::success();
  SBT S(InputFiles, OutputFile, Err);
  if (Err)
    return std::move(Err);
  return std::move(S);
}

const std::string *SBT::BIN_NAME = nullptr;

SBT::SBT(
  const cl::list<std::string> &InputFilesList,
  const std::string &OutputFile,
  Error &E)
  :
  OutputFile(OutputFile),
  Context(new LLVMContext),
  Builder(*Context),
  Module(new llvm::Module("main", *Context))
{
  for (auto File : InputFilesList) {
    if (!sys::fs::exists(File)) {
      SBTError SE(File);
      SE << "No such file.\n";
      E = make_error<SBTError>(std::move(SE));
      return;
    }
    InputFiles.push_back(File);
  }
}

Error SBT::genHello()
{
  // constants
  static const int SYS_EXIT = 1;
  static const int SYS_WRITE = 4;

  // types
  Type *Int8 = Type::getInt8Ty(*Context);
  Type *Int32 = Type::getInt32Ty(*Context);

  // syscall
  FunctionType *FTSyscall =
    FunctionType::get(Int32, { Int32, Int32 }, VAR_ARG);
  Function *FSyscall = Function::Create(FTSyscall,
      Function::ExternalLinkage, "syscall", &*Module);

  // set data
  std::string Hello("Hello, World!\n");
  GlobalVariable *Msg =
    new GlobalVariable(
      *Module,
      ArrayType::get(Int8, Hello.size()),
      CONSTANT,
      GlobalVariable::PrivateLinkage,
      ConstantDataArray::getString(*Context, Hello.c_str(), !ADD_NULL),
      "msg");

  // _start
  FunctionType *FTStart = FunctionType::get(Int32, {}, !VAR_ARG);
  Function *FStart =
    Function::Create(FTStart, Function::ExternalLinkage, "_start", &*Module);

  // entry basic block
  BasicBlock *BB = BasicBlock::Create(*Context, "entry", FStart);
  Builder.SetInsertPoint(BB);

  // call write
  Value *SC = ConstantInt::get(Int32, APInt(32, SYS_WRITE, SIGNED));
  Value *FD = ConstantInt::get(Int32, APInt(32, 1, SIGNED));
  Value *Ptr = Msg;
  Value *Len = ConstantInt::get(Int32, APInt(32, Hello.size(), SIGNED));
  std::vector<Value *> Args = { SC, FD, Ptr, Len };
  Builder.CreateCall(FSyscall, Args);

  // call exit
  SC = ConstantInt::get(Int32, APInt(32, SYS_EXIT, SIGNED));
  Value *RC = ConstantInt::get(Int32, APInt(32, 0, SIGNED));
  Args = { SC, RC };
  Builder.CreateCall(FSyscall, Args);
  Builder.CreateRet(RC);
  return Error::success();
}

Error SBT::run()
{
  // genHello();

  for (auto &F : InputFiles) {
    Error E = translate(F);
    if (E)
      return E;
  }
  return Error::success();
}

void SBT::write()
{
  std::error_code EC;
  raw_fd_ostream OS(OutputFile, EC, sys::fs::F_None);
  WriteBitcodeToFile(&*Module, OS);
  OS.flush();
}

Error SBT::translate(const std::string &File)
{
  SBTError SE(File);
  auto E = [&SE](){
    return make_error<SBTError>(std::move(SE));
  };

  // attempt to open the binary.
  Expected<object::OwningBinary<object::Binary>> Exp =
    object::createBinary(File);
  if (!Exp)
    return Exp.takeError();
  object::OwningBinary<object::Binary> &OB = Exp.get();
  object::Binary *Bin = OB.getBinary();

  if (!object::ObjectFile::classof(Bin)) {
    SE << "Unrecognized file type.\n";
    return E();
  }

  object::ObjectFile *OBJ = dyn_cast<object::ObjectFile>(Bin);

  outs() << OBJ->getFileName() << ": file format: " << OBJ->getFileFormatName()
         << "\n";

  // get target
  Triple Triple("riscv32-unknown-elf");
  Triple.setArch(Triple::ArchType(OBJ->getArch()));
  std::string TripleName = Triple.getTriple();
  outs() << "Triple: " << TripleName << "\n";

  std::string StrError;
  const Target *Target = TargetRegistry::lookupTarget(TripleName, StrError);
  if (!Target) {
    SE << "Target not found: " << TripleName << ": " << StrError << "\n";
    return E();
  }

  std::unique_ptr<const MCRegisterInfo> MRI(
      Target->createMCRegInfo(TripleName));
  if (!MRI) {
    SE << "No register info for target " << TripleName << "\n";
    return E();
  }

  // Set up disassembler.
  std::unique_ptr<const MCAsmInfo> AsmInfo(
      Target->createMCAsmInfo(*MRI, TripleName));
  if (!AsmInfo) {
    SE << "No assembly info for target " << TripleName << "\n";
    return E();
  }

  SubtargetFeatures Features;
  std::unique_ptr<const MCSubtargetInfo> STI(
      Target->createMCSubtargetInfo(TripleName, "", Features.getString()));
  if (!STI) {
    SE << "No subtarget info for target " << TripleName << "\n";
    return E();
  }

  std::unique_ptr<const MCObjectFileInfo> MOFI(new MCObjectFileInfo);
  MCContext Ctx(AsmInfo.get(), MRI.get(), MOFI.get());

  std::unique_ptr<const MCDisassembler> DisAsm(
      Target->createMCDisassembler(*STI, Ctx));
  if (!DisAsm) {
    SE << "No disassembler for target " << TripleName << "\n";
    return E();
  }

  std::unique_ptr<const MCInstrInfo> MII(Target->createMCInstrInfo());
  if (!MII) {
    SE << "No instruction info for target " << TripleName << "\n";
    return E();
  }

  return Error::success();
}

/// SBTError ///

char SBTError::ID = 'S';

///

void handleError(Error &&E)
{
  Error E2 = llvm::handleErrors(std::move(E),
    [](const SBTError &SE) {
      // errs() << "SBTError:\n";
      SE.log(errs());
      errs().flush();
      std::exit(EXIT_FAILURE);
    });

  if (E2) {
    logAllUnhandledErrors(std::move(E2), errs(), *SBT::BIN_NAME + ": error: ");
    std::exit(EXIT_FAILURE);
  }
}

} // sbt

int main(int argc, char *argv[])
{
  // test();
  // ExitOnError ExitOnErr;

  // options
  cl::list<std::string> InputFiles(
      cl::Positional,
      cl::desc("<input object files>"),
      cl::OneOrMore);

  cl::opt<std::string> OutputFileOpt(
      "o",
      cl::desc("output filename"));

  // parse args
  cl::ParseCommandLineOptions(argc, argv);

  std::string OutputFile;
  if (OutputFileOpt.empty()) {
    OutputFile = "x86-" + InputFiles.front();
    // remove file extension
    OutputFile = OutputFile.substr(0, OutputFile.find_last_of('.')) + ".bc";
  } else
    OutputFile = OutputFileOpt;

  // start SBT
  sbt::SBT::init();

  struct SBTFinish
  {
    ~SBTFinish()
    {
      sbt::SBT::finish();
    }
  } Finish;

  Expected<sbt::SBT> Exp = sbt::SBT::create(InputFiles, OutputFile);
  if (!Exp)
    sbt::handleError(Exp.takeError());
  sbt::SBT &SBT = Exp.get();

  sbt::handleError(SBT.run());
  SBT.dump();

  errs() << "Error: Incomplete translation\n";
  std::exit(EXIT_FAILURE);
  SBT.write();

  return EXIT_SUCCESS;
}
<commit_msg>Trying to make RISCV disassembler work.<commit_after>#include "sbt.h"

#include <llvm/Bitcode/BitcodeWriter.h>
#include <llvm/MC/MCAsmInfo.h>
#include <llvm/MC/MCContext.h>
#include <llvm/MC/MCDisassembler/MCDisassembler.h>
#include <llvm/MC/MCInstrInfo.h>
#include <llvm/MC/MCObjectFileInfo.h>
#include <llvm/MC/MCRegisterInfo.h>
#include <llvm/Object/Binary.h>
#include <llvm/Object/ELF.h>
#include <llvm/Object/MachO.h>
#include <llvm/Object/ObjectFile.h>
#include <llvm/Support/FileSystem.h>
#include <llvm/Support/Signals.h>
#include <llvm/Support/TargetRegistry.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Target/TargetMachine.h>

using namespace llvm;

namespace sbt {

void SBT::init()
{
  BIN_NAME = new std::string("riscv-sbt");

  // print a stack trace if we signal out.
  sys::PrintStackTraceOnErrorSignal(*BIN_NAME);

  InitializeAllTargetInfos();
  InitializeAllTargetMCs();
  InitializeAllAsmParsers();
  InitializeAllDisassemblers();
}

void SBT::finish()
{
  delete BIN_NAME;
  llvm_shutdown();
}

Expected<SBT> SBT::create(
    const llvm::cl::list<std::string> &InputFiles,
    const std::string &OutputFile)
{
  Error Err = Error::success();
  SBT S(InputFiles, OutputFile, Err);
  if (Err)
    return std::move(Err);
  return std::move(S);
}

const std::string *SBT::BIN_NAME = nullptr;

SBT::SBT(
  const cl::list<std::string> &InputFilesList,
  const std::string &OutputFile,
  Error &E)
  :
  OutputFile(OutputFile),
  Context(new LLVMContext),
  Builder(*Context),
  Module(new llvm::Module("main", *Context))
{
  for (auto File : InputFilesList) {
    if (!sys::fs::exists(File)) {
      SBTError SE(File);
      SE << "No such file.\n";
      E = make_error<SBTError>(std::move(SE));
      return;
    }
    InputFiles.push_back(File);
  }
}

Error SBT::genHello()
{
  // constants
  static const int SYS_EXIT = 1;
  static const int SYS_WRITE = 4;

  // types
  Type *Int8 = Type::getInt8Ty(*Context);
  Type *Int32 = Type::getInt32Ty(*Context);

  // syscall
  FunctionType *FTSyscall =
    FunctionType::get(Int32, { Int32, Int32 }, VAR_ARG);
  Function *FSyscall = Function::Create(FTSyscall,
      Function::ExternalLinkage, "syscall", &*Module);

  // set data
  std::string Hello("Hello, World!\n");
  GlobalVariable *Msg =
    new GlobalVariable(
      *Module,
      ArrayType::get(Int8, Hello.size()),
      CONSTANT,
      GlobalVariable::PrivateLinkage,
      ConstantDataArray::getString(*Context, Hello.c_str(), !ADD_NULL),
      "msg");

  // _start
  FunctionType *FTStart = FunctionType::get(Int32, {}, !VAR_ARG);
  Function *FStart =
    Function::Create(FTStart, Function::ExternalLinkage, "_start", &*Module);

  // entry basic block
  BasicBlock *BB = BasicBlock::Create(*Context, "entry", FStart);
  Builder.SetInsertPoint(BB);

  // call write
  Value *SC = ConstantInt::get(Int32, APInt(32, SYS_WRITE, SIGNED));
  Value *FD = ConstantInt::get(Int32, APInt(32, 1, SIGNED));
  Value *Ptr = Msg;
  Value *Len = ConstantInt::get(Int32, APInt(32, Hello.size(), SIGNED));
  std::vector<Value *> Args = { SC, FD, Ptr, Len };
  Builder.CreateCall(FSyscall, Args);

  // call exit
  SC = ConstantInt::get(Int32, APInt(32, SYS_EXIT, SIGNED));
  Value *RC = ConstantInt::get(Int32, APInt(32, 0, SIGNED));
  Args = { SC, RC };
  Builder.CreateCall(FSyscall, Args);
  Builder.CreateRet(RC);
  return Error::success();
}

Error SBT::run()
{
  // genHello();

  for (auto &F : InputFiles) {
    Error E = translate(F);
    if (E)
      return E;
  }
  return Error::success();
}

void SBT::write()
{
  std::error_code EC;
  raw_fd_ostream OS(OutputFile, EC, sys::fs::F_None);
  WriteBitcodeToFile(&*Module, OS);
  OS.flush();
}

static Expected<std::vector<std::pair<uint64_t, StringRef>>>
getSymbolsList(const object::ObjectFile *Obj, const object::SectionRef &Section)
{
  uint64_t SectionAddr = Section.getAddress();

  std::error_code EC;
  // Make a list of all the symbols in this section.
  std::vector<std::pair<uint64_t, StringRef>> Symbols;
  for (auto Symbol : Obj->symbols()) {
    if (!Section.containsSymbol(Symbol))
      continue;

    auto Exp = Symbol.getAddress();
    if (!Exp)
      return Exp.takeError();
    auto &Address = Exp.get();
    Address -= SectionAddr;

    auto Exp2 = Symbol.getName();
    if (!Exp2)
      return Exp2.takeError();
    auto &Name = Exp2.get();
    Symbols.push_back(std::make_pair(Address, Name));
  }

  // Sort the symbols by address, just in case they didn't come in that way.
  array_pod_sort(Symbols.begin(), Symbols.end());
  return Symbols;
}

static uint64_t getELFOffset(const object::SectionRef &Section)
{
  object::DataRefImpl Sec = Section.getRawDataRefImpl();
  auto sec = reinterpret_cast<
    const object::Elf_Shdr_Impl<
      object::ELFType<support::little, false>> *>(Sec.p);
  return sec->sh_offset;
}

Error SBT::translate(const std::string &File)
{
  SBTError SE(File);
  auto E = [&SE](){
    return make_error<SBTError>(std::move(SE));
  };

  // attempt to open the binary.
  Expected<object::OwningBinary<object::Binary>> Exp =
    object::createBinary(File);
  if (!Exp)
    return Exp.takeError();
  object::OwningBinary<object::Binary> &OB = Exp.get();
  object::Binary *Bin = OB.getBinary();

  if (!object::ObjectFile::classof(Bin)) {
    SE << "Unrecognized file type.\n";
    return E();
  }

  object::ObjectFile *Obj = dyn_cast<object::ObjectFile>(Bin);

  outs() << Obj->getFileName() << ": file format: " << Obj->getFileFormatName()
         << "\n";

  // get target
  Triple Triple("riscv32-unknown-elf");
  Triple.setArch(Triple::ArchType(Obj->getArch()));
  std::string TripleName = Triple.getTriple();
  outs() << "Triple: " << TripleName << "\n";

  std::string StrError;
  const Target *Target = TargetRegistry::lookupTarget(TripleName, StrError);
  if (!Target) {
    SE << "Target not found: " << TripleName << ": " << StrError << "\n";
    return E();
  }

  std::unique_ptr<const MCRegisterInfo> MRI(
      Target->createMCRegInfo(TripleName));
  if (!MRI) {
    SE << "No register info for target " << TripleName << "\n";
    return E();
  }

  // Set up disassembler.
  std::unique_ptr<const MCAsmInfo> AsmInfo(
      Target->createMCAsmInfo(*MRI, TripleName));
  if (!AsmInfo) {
    SE << "No assembly info for target " << TripleName << "\n";
    return E();
  }

  SubtargetFeatures Features;
  std::unique_ptr<const MCSubtargetInfo> STI(
      Target->createMCSubtargetInfo(TripleName, "", Features.getString()));
  if (!STI) {
    SE << "No subtarget info for target " << TripleName << "\n";
    return E();
  }

  std::unique_ptr<const MCObjectFileInfo> MOFI(new MCObjectFileInfo);
  MCContext Ctx(AsmInfo.get(), MRI.get(), MOFI.get());

  std::unique_ptr<const MCDisassembler> DisAsm(
      Target->createMCDisassembler(*STI, Ctx));
  if (!DisAsm) {
    SE << "No disassembler for target " << TripleName << "\n";
    return E();
  }

  std::unique_ptr<const MCInstrInfo> MII(Target->createMCInstrInfo());
  if (!MII) {
    SE << "No instruction info for target " << TripleName << "\n";
    return E();
  }

  // sections
  for (const object::SectionRef &Section : Obj->sections()) {
    if (!Section.isText())
      continue;

    uint64_t SectionAddr = Section.getAddress();

    StringRef SegmentName = "";
    if (const object::MachOObjectFile *MachO =
        dyn_cast<const object::MachOObjectFile>(Obj)) {
      object::DataRefImpl DR = Section.getRawDataRefImpl();
      SegmentName = MachO->getSectionFinalSegmentName(DR);
    }
    StringRef Name;
    std::error_code EC = Section.getName(Name);
    if (EC) {
      SE << "Failed to get Section Name";
      return E();
    }
#ifndef NDEBUG
    outs() << "Disassembly of section ";
    if (!SegmentName.empty())
      outs() << SegmentName << ",";
    outs() << Name << ':';
#endif

    StringRef BytesStr;
    EC = Section.getContents(BytesStr);
    if (EC) {
      SE << "Failed to get Section Contents";
      return E();
    }
    ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(BytesStr.data()),
                            BytesStr.size());

    // Make a list of all the symbols in this section.
    auto Exp = getSymbolsList(Obj, Section);
    if (!Exp)
      return Exp.takeError();
    auto &Symbols = Exp.get();
    // If the section has no symbols just insert a dummy one and disassemble
    // the whole section.
    if (Symbols.empty())
      Symbols.push_back(std::make_pair(0, Name));

    uint64_t SectSize = Section.getSize();
    // Disassemble symbol by symbol.
    for (unsigned si = 0, se = Symbols.size(); si != se; ++si) {
      uint64_t Start = Symbols[si].first;
      uint64_t End;

      // The end is either the size of the section or the beginning of the next
      // symbol.
      if (si == se - 1)
        End = SectSize;
      // Make sure this symbol takes up space.
      else if (Symbols[si + 1].first != Start)
        End = Symbols[si + 1].first - 1;
      else
        // This symbol has the same address as the next symbol. Skip it.
        continue;

#ifndef NDEBUG
      outs() << '\n' << Symbols[si].second << ":\n";
#endif

#ifndef NDEBUG
      raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls();
#else
      raw_ostream &DebugOut = nulls();
#endif

      /*
      uint64_t eoffset = SectionAddr;
      // Relocatable object
      if (SectionAddr == 0)
        // TODO handle errors
        eoffset = getELFOffset(Section);
      */

      /*
      if (Symbols[si].second == "main")
        IP->StartMainFunction(Start + eoffset);
      else
        IP->StartFunction(
            Twine("a").concat(Twine::utohexstr(Start + eoffset)).str(),
            Start + eoffset);
       */

      // instructions
      uint64_t Size;
      outs() << "SectionAddr = " << SectionAddr << "\n";
      outs() << "Bytes = " << Bytes.size() << "\n";
      for (uint64_t Index = Start; Index < End; Index += Size) {
        outs() << "Index = " << Index << "\n";

        MCInst Inst;

        // IP->UpdateCurAddr(Index + eoffset);
        MCDisassembler::DecodeStatus st =
          DisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
            SectionAddr + Index, DebugOut, nulls());
        if (st == MCDisassembler::DecodeStatus::Success) {
          outs() << "*\n";
          Inst.print(outs());
          /*
#ifndef NDEBUG
          outs() << format("%8" PRIx64 ":", eoffset + Index);
          outs() << "\t";
          DumpBytes(StringRef(BytesStr.data() + Index, Size));
#endif
          IP->printInst(&Inst, outs(), "");
#ifdef NDEBUG
          if (++NumProcessed % 10000 == 0) {
            outs() << ".";
          }
#endif
#ifndef NDEBUG
          outs() << "\n";
#endif
        */
        } else {
          SE << "Invalid instruction encoding\n";
          return E();
        }
      } // instructions
      // IP->FinishFunction();
    } // symbols
  } // sections
  // IP->FinishModule();
  // OptimizeAndWriteBitcode(&*IP);

  return Error::success();
}

/// SBTError ///

char SBTError::ID = 'S';

///

void handleError(Error &&E)
{
  Error E2 = llvm::handleErrors(std::move(E),
    [](const SBTError &SE) {
      // errs() << "SBTError:\n";
      SE.log(errs());
      errs() << "\n";
      errs().flush();
      std::exit(EXIT_FAILURE);
    });

  if (E2) {
    logAllUnhandledErrors(std::move(E2), errs(), *SBT::BIN_NAME + ": error: ");
    std::exit(EXIT_FAILURE);
  }
}

} // sbt

int main(int argc, char *argv[])
{
  // test();
  // ExitOnError ExitOnErr;

  // options
  cl::list<std::string> InputFiles(
      cl::Positional,
      cl::desc("<input object files>"),
      cl::OneOrMore);

  cl::opt<std::string> OutputFileOpt(
      "o",
      cl::desc("output filename"));

  // parse args
  cl::ParseCommandLineOptions(argc, argv);

  std::string OutputFile;
  if (OutputFileOpt.empty()) {
    OutputFile = "x86-" + InputFiles.front();
    // remove file extension
    OutputFile = OutputFile.substr(0, OutputFile.find_last_of('.')) + ".bc";
  } else
    OutputFile = OutputFileOpt;

  // start SBT
  sbt::SBT::init();

  struct SBTFinish
  {
    ~SBTFinish()
    {
      sbt::SBT::finish();
    }
  } Finish;

  Expected<sbt::SBT> Exp = sbt::SBT::create(InputFiles, OutputFile);
  if (!Exp)
    sbt::handleError(Exp.takeError());
  sbt::SBT &SBT = Exp.get();

  sbt::handleError(SBT.run());
  SBT.dump();

  errs() << "Error: Incomplete translation\n";
  std::exit(EXIT_FAILURE);
  SBT.write();

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>// Copyright 2012 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <string>
using std::string;

#include <Exceptions.hpp>
using isa::Exceptions::OpenCLError;
#include <CLData.hpp>
using isa::OpenCL::CLData;
#include <utils.hpp>
using isa::utils::toStringValue;
using isa::utils::giga;
#include <Kernel.hpp>
using isa::OpenCL::Kernel;
#include <Observation.hpp>
using AstroData::Observation;

#ifndef SNR_HPP
#define SNR_HPP

namespace PulsarSearch {

// OpenCL SNR
template< typename T > class SNR : public Kernel< T > {
public:
	SNR(string name, string dataType);

	void generateCode() throw (OpenCLError);
	void operator()(CLData< T > * input, CLData< T > * output) throw (OpenCLError);

	inline void setNrDMsPerBlock(unsigned int DMs);
	inline void setNrPeriodsPerBlock(unsigned int periods);

	inline void setTransientPipeline();
	inline void setPulsarPipeline();

	inline void setObservation(Observation< T > * obs);

private:
	cl::NDRange globalSize;
	cl::NDRange localSize;

	unsigned int nrDMsPerBlock;
	unsigned int nrPeriodsPerBlock;

	bool transientPipeline;
	bool pulsarPipeline;

	Observation< T > * observation;
};

// Implementation
template< typename T > SNR< T >::SNR(string name, string dataType) : Kernel< T >(name, dataType), globalSize(cl::NDRange(1, 1, 1)), localSize(cl::NDRange(1, 1, 1)), nrDMsPerBlock(0), nrPeriodsPerBlock(0), transientPipeline(false), pulsarPipeline(false), observation(0) {}

template< typename T > void SNR< T >::generateCode() throw (OpenCLError) {
	delete this->code;
	this->code = new string();

	if ( transientPipeline ) {
		throw OpenCLError("Transient pipeline not implemented.");
	} else if ( pulsarPipeline ) {
		// Begin kernel's template
		string nrDMsPerBlock_s = toStringValue< unsigned int >(nrDMsPerBlock);
		string nrPeriodsPerBlock_s = toStringValue< unsigned int >(nrPeriodsPerBlock);
		string nrBins_s = toStringValue< unsigned int >(observation->getNrBins());
		string nrPeriods_s = toStringValue< unsigned int >(observation->getNrPeriods());
		string nrPaddedDMs_s = toStringValue< unsigned int >(observation->getNrPaddedDMs());
		string nrBinsInverse_s = toStringValue< float >(1.0f / observation->getNrBins());

		*(this->code) = "__kernel void " + this->name + "(__global const " + this->dataType + " * const restrict foldedData, __global " + this->dataType + " * const restrict snrs) {\n"
			"const unsigned int dm = (get_group_id(0) * " + nrDMsPerBlock_s + ") + get_local_id(0);\n"
			"const unsigned int period = (get_group_id(1) * " + nrPeriodsPerBlock_s + ") + get_local_id(1);\n"
			+ this->dataType + " average = 0;\n"
			+ this->dataType + " rms = 0;\n"
			+ this->dataType + " max = 0;\n"
			"\n"
			"for ( unsigned int bin = 0; bin < " + nrBins_s + "; bin++ ) {\n"
			"const " + this->dataType + " globalItem = foldedData[(bin * " + nrPeriods_s + " * " + nrPaddedDMs_s + ") + (period * " + nrPaddedDMs_s + ") + dm];\n"
			"average += globalItem;\n"
			"rms += (globalItem * globalItem);\n"
			"max = fmax(max, globalItem);\n"
			"}\n"
			"average *= " + nrBinsInverse_s + "f;\n"
			"rms *= " + nrBinsInverse_s + "f;\n"
			"snrs[(period * " + nrPaddedDMs_s + ") + dm] = (max - average) / native_sqrt(rms);\n"
			"}\n";
		// End kernel's template

		globalSize = cl::NDRange(observation->getNrPaddedDMs(), observation->getNrPeriods());
		localSize = cl::NDRange(nrDMsPerBlock, nrPeriodsPerBlock);

		this->gflop = giga(static_cast< long long unsigned int >(observation->getNrDMs()) * observation->getNrPeriods() * ((observation->getNrBins() * 3) + 4));
		this->gb = giga(static_cast< long long unsigned int >(observation->getNrDMs()) * observation->getNrPeriods() * ((observation->getNrBins() * sizeof(T)) + sizeof(T)));
	} else {
		throw OpenCLError("Pipeline not implemented.");
	}

	this->compile();
}

template< typename T > void SNR< T >::operator()(CLData< T > * input, CLData< T > * output) throw (OpenCLError) {
	this->setArgument(0, *(input->getDeviceData()));
	this->setArgument(1, *(output->getDeviceData()));

	this->run(globalSize, localSize);
}

template< typename T > inline void SNR< T >::setNrDMsPerBlock(unsigned int DMs) {
	nrDMsPerBlock = DMs;
}

template< typename T > inline void SNR< T >::setNrPeriodsPerBlock(unsigned int periods) {
	nrPeriodsPerBlock = periods;
}

template< typename T > inline void SNR< T >::setTransientPipeline() {
	transientPipeline = true;
	pulsarPipeline = false;
}

template< typename T > inline void SNR< T >::setPulsarPipeline() {
	pulsarPipeline = true;
	transientPipeline = false;
}

template< typename T >inline void SNR< T >::setObservation(Observation< T > *obs) {
	observation = obs;
}

} // PulsarSearch

#endif // SNR_HPP
<commit_msg>Started the refactoring. Added sequential and OpenCL SNR.<commit_after>// Copyright 2014 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <string>

#include <utils.hpp>
#include <Observation.hpp>

#ifndef SNR_HPP
#define SNR_HPP

namespace PulsarSearch {

// Sequential SNR
template< typename T > void snrFoldedTS(const AstroData::Observation< T > & observation, const std::vector< T > & foldedTS, std::vector< T > & snrs);
// OpenCL SNR
template< typename T > std::string getSNROpenCL(const unsigned int nrDMsPerBlock, const unsigned int nrPeriodsPerBlock, const unsigned int nrDMsPerThread, const unsigned int nrPeriodsPerThread, std::string & dataType, const AstroData::Observation< T > & observation);

// Implementations
template< typename T > void snrFoldedTS(AstroData::Observation< T > & observation, const std::vector< T > & foldedTS, std::vector< T > & snrs) {
	for ( unsigned int period = 0; period < observation.getNrPeriods(); period++ ) {
		for ( unsigned int dm = 0; dm < observation.getNrDMs(); dm++ ) {
			T max = 0;
			float average = 0.0f;
			float rms = 0.0f;

			for ( unsigned int bin = 0; bin < observation.getNrBins(); bin++ ) {
				T value = foldedTS[(bin * observation.getNrPeriods() * observation.getNrPaddedDMs()) + (period * observation.getNrPaddedDMs()) + dm];

				average += value;
				rms += (value * value);

				if ( value > max ) {
					max = value;
				}
			}
			average /= observation.getNrBins();
			rms = sqrt(rms / observation.getNrBins());

			snrs[(period * observation.getNrPaddedDMs()) + dm] = (max - average) / rms;
		}
	}
}

template< typename T > std::string getSNROpenCL(const unsigned int nrDMsPerBlock, const unsigned int nrPeriodsPerBlock, const unsigned int nrDMsPerThread, const unsigned int nrPeriodsPerThread, std::string & dataType, const AstroData::Observation< T > & observation) {
  std::string * code = new std::string();

  // Begin kernel's template
  std::string nrPaddedDMs_s = isa::utils::toString< unsigned int >(observation.getNrPaddedDMs());
  std::string nrBinsInverse_s = isa::utils::toString< float >(1.0f / observation.getNrBins());

  *code = "__kernel void snr(__global const " + dataType + " * const restrict foldedData, __global " + dataType + " * const restrict snrs) {\n"
    "<%DEF_DM%>"
    "<%DEF_PERIOD%>"
    + dataType + " globalItem = 0;\n"
    + dataType + " average = 0;\n"
    + dataType + " rms = 0;\n"
    + dataType + " max = 0;\n"
    "\n"
    "<%COMPUTE%>";
    std::string defDMsTemplate = "const unsigned int dm<%DM_NUM%> = (get_group_id(0) * " + isa::utils::toString< unsigned int >(nrDMsPerBlock * nrDMsPerThread) + ") + get_local_id(0) + <%DM_NUM%>;\n";
  std::string defPeriodsTemplate = "const unsigned int period<%PERIOD_NUM%> = (get_group_id(1) * " + isa::utils::toString< unsigned int >(nrPeriodsPerBlock * nrPeriodsPerThread) + ") + get_local_id(1) + <%PERIOD_NUM%>;\n";
  std::string computeTemplate = "average = 0;\n"
    " rms = 0;\n"
    " max = 0;\n"
    "for ( unsigned int bin = 0; bin < " + isa::utils::toString< unsigned int >(observation.getNrBins()) + "; bin++ ) {\n"
    "globalItem = foldedData[(bin * " + isa::utils::toString< unsigned int >(observation.getNrPeriods()) + " * " + nrPaddedDMs_s + ") + ((period + <%PERIOD_NUM%>) * " + nrPaddedDMs_s + ") + dm + <%DM_NUM%>];\n"
    "average += globalItem;\n"
    "rms += (globalItem * globalItem);\n"
    "max = fmax(max, globalItem);\n"
    "}\n"
    "average *= " + nrBinsInverse_s + "f;\n"
    "rms *= " + nrBinsInverse_s + "f;\n"
    "snrs[((period + <%PERIOD_NUM%>) * " + nrPaddedDMs_s + ") + dm + <%DM_NUM%>] = (max - average) / native_sqrt(rms);\n"
    "}\n";
  // End kernel's template

  std::string * defDM_s = new std::string();
  std::string * defPeriod_s = new std::string();
  std::string * compute_s = new std::string();

  for ( unsigned int dm = 0; dm < nrDMsPerThread; dm++ ) {
    std::string dm_s = isa::utils::toString< unsigned int >(dm);
    std::string * temp_s = 0;

    temp_s = isa::utils::replace(&defDMsTemplate, "<%DM_NUM%>", dm_s);
    defDM_s->append(*temp_s);
    delete temp_s;
  }
  for ( unsigned int period = 0; period < nrPeriodsPerThread; period++ ) {
    std::string period_s = isa::utils::toString< unsigned int >(period);
    std::string * temp_s = 0;

    temp_s = isa::utils::replace(&defPeriodsTemplate, "<%PERIOD_NUM%>", period_s);
    defPeriod_s->append(*temp_s);
    delete temp_s;

    for ( unsigned int dm = 0; dm < nrDMsPerThread; dm++ ) {
      std::string dm_s = isa::utils::toString< unsigned int >(dm);

      temp_s = isa::utils::replace(&computeTemplate, "<%PERIOD_NUM%>", period_s);
      temp_s = isa::utils::replace(temp_s, "<%DM_NUM%>", dm_s, true);
      compute_s->append(*temp_s);
      delete temp_s;
    }
  }

  code = isa::utils::replace(code, "<%DEF_DM%>", *defDM_s, true);
  code = isa::utils::replace(code, "<%DEF_PERIOD%>", *defPeriod_s, true);
  code = isa::utils::replace(code, "<%COMPUTE%>", *compute_s, true);

  return code;
}

} // PulsarSearch

#endif // SNR_HPP

<|endoftext|>