<commit_before>//
// shard.cpp
// *********
//
// Copyright (c) 2018 Sharon W (sharon at aegis dot gg)
//
// Distributed under the MIT License. (See accompanying file LICENSE)
//

#include "aegis/config.hpp"
#include "aegis/shard.hpp"

namespace aegis
{

AEGIS_DECL shard::shard(asio::io_context & _io, websocketpp::client<websocketpp::config::asio_tls_client> & _ws)
    : write_timer(_io)
    , heartbeattime(0)
    , sequence(0)
    , connection_state(bot_status::Uninitialized)
    , ws_write(_io)
    , _io_context(_io)
    , transfer_bytes(0)
    , transfer_bytes_u(0)
    , _websocket(_ws)
{
}

AEGIS_DECL void shard::do_reset() AEGIS_NOEXCEPT
{
    heartbeat_ack = lastheartbeat = std::chrono::steady_clock::time_point();
    if (_connection != nullptr)
        _connection.reset();
    if (keepalivetimer != nullptr)
    {
        keepalivetimer->cancel();
        keepalivetimer.reset();
    }
    write_timer.cancel();
    ++counters.reconnects;
}

AEGIS_DECL void shard::set_connected()
{
    using namespace std::chrono_literals;
    write_timer.expires_after(600ms);
    write_timer.async_wait(asio::bind_executor(ws_write, std::bind(&shard::process_writes, this, std::placeholders::_1)));
    connection_state = bot_status::Online;
}

AEGIS_DECL bool shard::is_connected() const AEGIS_NOEXCEPT
{
    if (_connection == nullptr)
        return false;

    if ((connection_state == bot_status::Connecting) || (connection_state == bot_status::Online))
        return true;

    return false;
}

AEGIS_DECL void shard::send(std::string const & payload, websocketpp::frame::opcode::value op)
{
    if (!is_connected())
        return;
    asio::post(asio::bind_executor(ws_write, [_payload = payload, op, this]()
    {
        write_queue.push({ _payload, op });
    }));
}

AEGIS_DECL void shard::send_now(std::string const & payload, websocketpp::frame::opcode::value op)
{
    if (!is_connected())
        return;
    asio::post(asio::bind_executor(ws_write, [_payload = payload, op, this]()
    {
        last_ws_write = std::chrono::steady_clock::now();
        _connection->send(_payload, op);
    }));
}

AEGIS_DECL void shard::process_writes(const asio::error_code & ec)
{
    if (ec == asio::error::operation_aborted)
        return;
    using namespace std::chrono_literals;
    if ((connection_state == bot_status::Online
         || connection_state == bot_status::Connecting) && !write_queue.empty())
    {
        last_ws_write = std::chrono::steady_clock::now();

        auto msg = write_queue.front();
        write_queue.pop();

        _connection->send(std::get<0>(msg), std::get<1>(msg));
    }

    write_timer.expires_after(600ms);
    write_timer.async_wait(asio::bind_executor(ws_write, std::bind(&shard::process_writes, this, std::placeholders::_1)));
}

}
<commit_msg>Fix tuple/initializer-list issue<commit_after>//
// shard.cpp
// *********
//
// Copyright (c) 2018 Sharon W (sharon at aegis dot gg)
//
// Distributed under the MIT License. (See accompanying file LICENSE)
//

#include "aegis/config.hpp"
#include "aegis/shard.hpp"

namespace aegis
{

AEGIS_DECL shard::shard(asio::io_context & _io, websocketpp::client<websocketpp::config::asio_tls_client> & _ws)
    : write_timer(_io)
    , heartbeattime(0)
    , sequence(0)
    , connection_state(bot_status::Uninitialized)
    , ws_write(_io)
    , _io_context(_io)
    , transfer_bytes(0)
    , transfer_bytes_u(0)
    , _websocket(_ws)
{
}

AEGIS_DECL void shard::do_reset() AEGIS_NOEXCEPT
{
    heartbeat_ack = lastheartbeat = std::chrono::steady_clock::time_point();
    if (_connection != nullptr)
        _connection.reset();
    if (keepalivetimer != nullptr)
    {
        keepalivetimer->cancel();
        keepalivetimer.reset();
    }
    write_timer.cancel();
    ++counters.reconnects;
}

AEGIS_DECL void shard::set_connected()
{
    using namespace std::chrono_literals;
    write_timer.expires_after(600ms);
    write_timer.async_wait(asio::bind_executor(ws_write, std::bind(&shard::process_writes, this, std::placeholders::_1)));
    connection_state = bot_status::Online;
}

AEGIS_DECL bool shard::is_connected() const AEGIS_NOEXCEPT
{
    if (_connection == nullptr)
        return false;

    if ((connection_state == bot_status::Connecting) || (connection_state == bot_status::Online))
        return true;

    return false;
}

AEGIS_DECL void shard::send(std::string const & payload, websocketpp::frame::opcode::value op)
{
    if (!is_connected())
        return;
    asio::post(asio::bind_executor(ws_write, [_payload = payload, op, this]()
    {
        write_queue.push(std::make_tuple(_payload, op));
    }));
}

AEGIS_DECL void shard::send_now(std::string const & payload, websocketpp::frame::opcode::value op)
{
    if (!is_connected())
        return;
    asio::post(asio::bind_executor(ws_write, [_payload = payload, op, this]()
    {
        last_ws_write = std::chrono::steady_clock::now();
        _connection->send(_payload, op);
    }));
}

AEGIS_DECL void shard::process_writes(const asio::error_code & ec)
{
    if (ec == asio::error::operation_aborted)
        return;
    using namespace std::chrono_literals;
    if ((connection_state == bot_status::Online
         || connection_state == bot_status::Connecting) && !write_queue.empty())
    {
        last_ws_write = std::chrono::steady_clock::now();

        auto msg = write_queue.front();
        write_queue.pop();

        _connection->send(std::get<0>(msg), std::get<1>(msg));
    }

    write_timer.expires_after(600ms);
    write_timer.async_wait(asio::bind_executor(ws_write, std::bind(&shard::process_writes, this, std::placeholders::_1)));
}

}
<|endoftext|>


<commit_before>/*
 * Copyright 2015 C. Brett Witherspoon
 */

#ifndef INCLUDE_COMM_SOCKET_HPP_
#define INCLUDE_COMM_SOCKET_HPP_

#include <zmq.h>
#include <memory>
#include <stdexcept>
#include <string>

#include "comm/message.hpp"

namespace comm
{
//! An exception thrown on message socket errors
struct socket_error : public std::runtime_error
{
  explicit socket_error(const std::string& where, const std::string& what) :
      std::runtime_error(where + ": " + what)
  {
  }
  explicit socket_error(const std::string& where) :
      socket_error(where, zmq_strerror(zmq_errno()))
  {
  }
};

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

//! A messaging socket
class socket
{
  friend class context;
public:
  enum class types
  {
    request = ZMQ_REQ,
    reply   = ZMQ_REP
  };

  socket(const socket&) = delete;

  socket& operator=(const socket&) = delete;

  socket(socket&&)  = delete;

  socket& operator=(socket&& other) = delete;

  //! Deconstructs a message socket
  ~socket();

  /*!
   * \brief Assigns an address to the message socket
   * \param addr an address
   * \sa connect()
   */
  socket& bind(const std::string& addr);

  /*!
   * \brief Connects the message socket to an address
   * \param addr an address
   * \sa bind()
   */
  socket& connect(const std::string& addr);

  /*! \brief Sends a message on the socket
   *  \param msg a message
   *  \sa recv()
   */
  socket& send(const message& msg);

  /*! \brief Receives a message on the socket
   *  \param msg a message
   *  \sa send()
   */
  socket& recv(message& msg);

private:
  /*!
   * \brief Constructs a message socket
   * \param context a context
   * \param type a socket type
   */
  socket(void* context, types type);

  void* m_socket; //!< A ZeroMQ socket
};

socket::socket(void* context, socket::types type)
{
  m_socket = zmq_socket(context, static_cast<int>(type));
  if (m_socket == nullptr)
    throw socket_error(__func__);
}

socket::~socket()
{
  const int ms = 500;
  zmq_setsockopt(m_socket, ZMQ_LINGER, &ms, sizeof(int));
  zmq_close(m_socket);
}

socket& socket::bind(const std::string& addr)
{
  if (zmq_bind(m_socket, addr.c_str()) != 0)
    throw socket_error(__func__);

  return *this;
}

socket& socket::connect(const std::string& addr)
{
  if (zmq_connect(m_socket, addr.c_str()) != 0 )
    throw socket_error(__func__);

  return *this;
}

socket& socket::send(const message& msg)
{
  auto data = msg.data();
  auto size = msg.size();

  if (zmq_send(m_socket, data, size, 0) == -1)
    throw socket_error(__func__);

  return *this;
}

socket& socket::recv(message& msg)
{
  const std::size_t size = 1024;
  msg.resize(size);

  auto data = msg.data();

  int count = zmq_recv(m_socket, data, size, 0);

  if (count < 0)
    throw socket_error(__func__);

  if (static_cast<std::size_t>(count) > size)
    throw socket_error(__func__, "message truncated");

  msg.resize(static_cast<std::size_t>(count));
  msg.reset();

  return *this;
}

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

/*! \brief A messaging context
 *
 *  A factory for constructing message sockets which all share the same context.
 *  A messaging context is thread safe, but the sockets it creates are not. All
 *  sockets created by context must be destroyed before the deconstructor of the
 *  context is called or it will block.
 */
class context
{
public:
  //! Constructs a new messaging context
  context();

  /*!
   * \brief Deconstructs the messaging context
   *
   * After the context is destroyed any sockets it constructed will throw an
   * exception if blocked or used.
   */
  ~context();

  /*! \brief Constructs a new message socket
   *  \param type A message socket type
   *  \returns A new message socket
   */
  std::unique_ptr<socket> make_socket(socket::types type);

private:
  void* m_context;
};

context::context()
{
  m_context = zmq_ctx_new();
  if (m_context == nullptr)
    throw socket_error(__func__);
}

context::~context()
{
  zmq_ctx_destroy(m_context);
}

std::unique_ptr<socket> context::make_socket(socket::types type)
{
  return std::unique_ptr<socket>(new socket(m_context, type));
}

} /* namespace comm */

#endif /* INCLUDE_COMM_SOCKET_HPP_ */
<commit_msg>socket: make socket_error a nested class<commit_after>/*
 * Copyright 2015 C. Brett Witherspoon
 */

#ifndef INCLUDE_COMM_SOCKET_HPP_
#define INCLUDE_COMM_SOCKET_HPP_

#include <zmq.h>
#include <memory>
#include <stdexcept>
#include <string>

#include "comm/message.hpp"

namespace comm
{
//! A messaging socket
class socket
{
  friend class context;
public:
  enum class types
  {
    request = ZMQ_REQ,
    reply   = ZMQ_REP
  };

  //! An exception thrown on message socket errors
  struct socket_error : public std::runtime_error
  {
    explicit socket_error(const std::string& where, const std::string& what) :
        std::runtime_error(where + ": " + what)
    {
    }
    explicit socket_error(const std::string& where) :
        socket_error(where, zmq_strerror(zmq_errno()))
    {
    }
  };

  socket(const socket&) = delete;

  socket& operator=(const socket&) = delete;

  socket(socket&&)  = delete;

  socket& operator=(socket&& other) = delete;

  //! Deconstructs a message socket
  ~socket();

  /*!
   * \brief Assigns an address to the message socket
   * \param addr an address
   * \sa connect()
   */
  socket& bind(const std::string& addr);

  /*!
   * \brief Connects the message socket to an address
   * \param addr an address
   * \sa bind()
   */
  socket& connect(const std::string& addr);

  /*! \brief Sends a message on the socket
   *  \param msg a message
   *  \sa recv()
   */
  socket& send(const message& msg);

  /*! \brief Receives a message on the socket
   *  \param msg a message
   *  \sa send()
   */
  socket& recv(message& msg);

private:
  /*!
   * \brief Constructs a message socket
   * \param context a context
   * \param type a socket type
   */
  socket(void* context, types type);

  void* m_socket; //!< A ZeroMQ socket
};

socket::socket(void* context, socket::types type)
{
  m_socket = zmq_socket(context, static_cast<int>(type));
  if (m_socket == nullptr)
    throw socket_error(__func__);
}

socket::~socket()
{
  const int ms = 500;
  zmq_setsockopt(m_socket, ZMQ_LINGER, &ms, sizeof(int));
  zmq_close(m_socket);
}

socket& socket::bind(const std::string& addr)
{
  if (zmq_bind(m_socket, addr.c_str()) != 0)
    throw socket_error(__func__);

  return *this;
}

socket& socket::connect(const std::string& addr)
{
  if (zmq_connect(m_socket, addr.c_str()) != 0 )
    throw socket_error(__func__);

  return *this;
}

socket& socket::send(const message& msg)
{
  auto data = msg.data();
  auto size = msg.size();

  if (zmq_send(m_socket, data, size, 0) == -1)
    throw socket_error(__func__);

  return *this;
}

socket& socket::recv(message& msg)
{
  const std::size_t size = 1024;
  msg.resize(size);

  auto data = msg.data();

  int count = zmq_recv(m_socket, data, size, 0);

  if (count < 0)
    throw socket_error(__func__);

  if (static_cast<std::size_t>(count) > size)
    throw socket_error(__func__, "message truncated");

  msg.resize(static_cast<std::size_t>(count));
  msg.reset();

  return *this;
}

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

/*! \brief A messaging context
 *
 *  A factory for constructing message sockets which all share the same context.
 *  A messaging context is thread safe, but the sockets it creates are not. All
 *  sockets created by context must be destroyed before the deconstructor of the
 *  context is called or it will block.
 */
class context
{
public:
  //! Constructs a new messaging context
  context();

  /*!
   * \brief Deconstructs the messaging context
   *
   * After the context is destroyed any sockets it constructed will throw an
   * exception if blocked or used.
   */
  ~context();

  /*! \brief Constructs a new message socket
   *  \param type A message socket type
   *  \returns A new message socket
   */
  std::unique_ptr<socket> make_socket(socket::types type);

private:
  void* m_context;
};

context::context()
{
  m_context = zmq_ctx_new();
  if (m_context == nullptr)
    throw socket::socket_error(__func__);
}

context::~context()
{
  zmq_ctx_destroy(m_context);
}

std::unique_ptr<socket> context::make_socket(socket::types type)
{
  return std::unique_ptr<socket>(new socket(m_context, type));
}

} /* namespace comm */

#endif /* INCLUDE_COMM_SOCKET_HPP_ */
<|endoftext|>


<commit_before>#ifndef __MULTIDIMENSIONAL_ARRAY__CONST_ARRAY_HPP__
#define __MULTIDIMENSIONAL_ARRAY__CONST_ARRAY_HPP__

#include "size.hpp"

namespace MultidimensionalArray {
  template <class T>
  class Array;

  template <class T>
  class ConstSlice;

  template <class T>
  class ConstView;

  template <class T>
  class ConstArray {
    public:
      typedef T value_type;

      ConstArray();

      ConstArray(ConstArray const& other);
      ConstArray(ConstArray&& other);

      ConstArray(Array<T> const& other);
      ConstArray(Array<T>&& other);

      ConstArray(Size const& size);
      ConstArray(Size const& size, T const* ptr,
          bool responsible_for_deleting = false);

      ~ConstArray();

      void swap(ConstArray& other);
      void swap(ConstArray&& other);

      ConstView<T> view();

      bool resize(Size const& size);

      Size const& size() const { return size_; }
      size_t total_size() const { return size_.total_size(); }

      void set_pointer(T const* ptr, bool responsible_for_deleting = false);
      T const* get_pointer() const { return values_; }

      template <class... Args>
      T const& operator()(Args const&... args) const;

      T const& get(Size::SizeType const& index) const;

    private:
      friend class ConstSlice<T>;

      void cleanup();

      Size size_;
      T const* values_;
      bool deallocate_on_destruction_;
  };
};

#include "const_array_impl.hpp"

#endif
<commit_msg>Made Array friend of ConstArray.<commit_after>#ifndef __MULTIDIMENSIONAL_ARRAY__CONST_ARRAY_HPP__
#define __MULTIDIMENSIONAL_ARRAY__CONST_ARRAY_HPP__

#include "size.hpp"

namespace MultidimensionalArray {
  template <class T>
  class Array;

  template <class T>
  class ConstSlice;

  template <class T>
  class ConstView;

  template <class T>
  class ConstArray {
    public:
      typedef T value_type;

      ConstArray();

      ConstArray(ConstArray const& other);
      ConstArray(ConstArray&& other);

      ConstArray(Array<T> const& other);
      ConstArray(Array<T>&& other);

      ConstArray(Size const& size);
      ConstArray(Size const& size, T const* ptr,
          bool responsible_for_deleting = false);

      ~ConstArray();

      void swap(ConstArray& other);
      void swap(ConstArray&& other);

      ConstView<T> view();

      bool resize(Size const& size);

      Size const& size() const { return size_; }
      size_t total_size() const { return size_.total_size(); }

      void set_pointer(T const* ptr, bool responsible_for_deleting = false);
      T const* get_pointer() const { return values_; }

      template <class... Args>
      T const& operator()(Args const&... args) const;

      T const& get(Size::SizeType const& index) const;

    private:
      friend class Array<T>;
      friend class ConstSlice<T>;

      void cleanup();

      Size size_;
      T const* values_;
      bool deallocate_on_destruction_;
  };
};

#include "const_array_impl.hpp"

#endif
<|endoftext|>


<commit_before>#ifndef LIBICS3_ICS3_EEPROM_H_
#define LIBICS3_ICS3_EEPROM_H_

#include"ics3/eepparam.hpp"

#include<algorithm>

namespace ics {
  class ICS3;

  class EepRom {
    friend ICS3; // for ICS3::getRom()
  public:
    using size_type = std::size_t;
    static constexpr size_type length {64};
    using Container = std::array<uint8_t, length>;

    EepParam get(EepParam) const;
    void set(const EepParam&) noexcept;
    template<typename Iter>
    void write(Iter&&) const;
  private:
    explicit EepRom(const Container&);

    std::array<uint8_t, length> data;
  };

  inline ics::EepParam ics::EepRom::get(EepParam type) const {
    type.read(data); // throw std::out_of_range
    return type;
  }

  inline void EepRom::set(const EepParam& param) noexcept {
    param.write(data);
  }

  template<typename Iter>
  inline void EepRom::write(Iter&& dest) const {
    std::copy(data.cbegin(), data.cend(), dest);
  }

  inline EepRom::EepRom(const Container& src)
  : data(src) // for Ubuntu14.04 compiler
  {}
}

#endif // LIBICS3_ICS3_EEPROM_H_
<commit_msg>Omit explicit<commit_after>#ifndef LIBICS3_ICS3_EEPROM_H_
#define LIBICS3_ICS3_EEPROM_H_

#include"ics3/eepparam.hpp"

#include<algorithm>

namespace ics {
  class ICS3;

  class EepRom {
    friend ICS3; // for ICS3::getRom()
  public:
    using size_type = std::size_t;
    static constexpr size_type length {64};
    using Container = std::array<uint8_t, length>;

    EepParam get(EepParam) const;
    void set(const EepParam&) noexcept;
    template<typename Iter>
    void write(Iter&&) const;
  private:
    EepRom(const Container&); // non explicit, user cannot touch this

    std::array<uint8_t, length> data;
  };

  inline ics::EepParam ics::EepRom::get(EepParam type) const {
    type.read(data); // throw std::out_of_range
    return type;
  }

  inline void EepRom::set(const EepParam& param) noexcept {
    param.write(data);
  }

  template<typename Iter>
  inline void EepRom::write(Iter&& dest) const {
    std::copy(data.cbegin(), data.cend(), dest);
  }

  inline EepRom::EepRom(const Container& src)
  : data(src) // for Ubuntu14.04 compiler
  {}
}

#endif // LIBICS3_ICS3_EEPROM_H_
<|endoftext|>


<commit_before>#include <osgViewer/Viewer>
#include <osg/Texture2D>
#include <osg/MatrixTransform>
#include <osg/PolygonMode>
#include <osgDB/ReadFile>

#include "../objects/sphere.h"

int main(void) {
    //ref_ptr<ph::Sphere> sphere = new ph::Sphere(5, 10, 10);
    ref_ptr<StackedSphere> sphere = new StackedSphere(5, 200, 200);
    ref_ptr<Group> root = new Group();

    ref_ptr<Texture2D> texture = new Texture2D;
    ref_ptr<Image> image = osgDB::readImageFile("../Textures/EarthMap.jpg");
    texture->setWrap(Texture::WRAP_S, Texture::CLAMP);
    texture->setImage(image.get());

    root->addChild(sphere.get());

    // wenn man die Dreiecke mal sehen will:
     ref_ptr<PolygonMode> pm = new PolygonMode;
     pm->setMode(PolygonMode::FRONT_AND_BACK, PolygonMode::LINE);
     //root->getOrCreateStateSet()->setAttribute(pm.get());

    osgViewer::Viewer viewer;
    viewer.setSceneData(root.get());
    return viewer.run();
}
<commit_msg>fix merge<commit_after>#include <osgViewer/Viewer>
#include <osg/Texture2D>
#include <osg/MatrixTransform>
#include <osg/PolygonMode>
#include <osgDB/ReadFile>

#include "../objects/sphere.h"

int main(void) {
    //ref_ptr<ph::Sphere> sphere = new ph::Sphere(5, 10, 10);
    ref_ptr<StackedSphere> sphere = new StackedSphere(5, 200, 200);
    ref_ptr<Group> root = new Group();

    ref_ptr<Texture2D> texture = new Texture2D;
    ref_ptr<Image> image = osgDB::readImageFile("../Textures/EarthMap.jpg");
    texture->setWrap(Texture::WRAP_S, Texture::CLAMP);
    texture->setImage(image.get());
    root->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture.get());

    root->addChild(sphere.get());

    // wenn man die Dreiecke mal sehen will:
     ref_ptr<PolygonMode> pm = new PolygonMode;
     pm->setMode(PolygonMode::FRONT_AND_BACK, PolygonMode::LINE);
     //root->getOrCreateStateSet()->setAttribute(pm.get());

    osgViewer::Viewer viewer;
    viewer.setSceneData(root.get());
    return viewer.run();
}
<|endoftext|>


<commit_before>/*
 * \copyright Copyright 2015 Xiang Zhang All Rights Reserved.
 * \license @{
 *
 * 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.
 *
 * @}
 */

/* Disclaimer: these tests are not complete. In particular, we do not test the
 * variants of order, transpose, uppper-lower, diagonal and side choices. We
 * always use row-major, no transpose, upper matrix, non-unit diagonal and left
 * side settings.
 */

#include <complex>
#include <cstdlib>
#include <random>

#include "gtest/gtest.h"
#include "thunder/linalg/cxxblas.hpp"

namespace thunder {
namespace linalg {
namespace {

template < typename D >
void expectEq(const D &a, const D &b) {
  EXPECT_FLOAT_EQ(a, b);
}
template < typename D >
void expectEq(const ::std::complex< D > &a, const ::std::complex< D > &b) {
  EXPECT_FLOAT_EQ(::std::real(a), ::std::real(b));
  EXPECT_FLOAT_EQ(::std::imag(a), ::std::imag(b));
}

template < typename D >
D conjg(const D &v) {
  return v;
}
template < typename D >
::std::complex< D > conjg(const ::std::complex< D > &v) {
  return ::std::conj(v);
}

template < typename D >
class RandomGenerator {
 public:
  template < typename G, typename R >
  D operator()(G *gen, R *dist) {
    return static_cast< D >((*dist)(*gen));
  }
};

template < typename D >
class RandomGenerator< ::std::complex< D > > {
 public:
  template < typename G, typename R >
  ::std::complex< D > operator()(G *gen, R *dist) {
    return ::std::complex< D >(
        static_cast< D >((*dist)(*gen)), static_cast< D >((*dist)(*gen)));
  }
};

template < typename D >
void gemmTest() {
  ::std::random_device rd;
  ::std::mt19937 gen(rd());
  ::std::uniform_real_distribution< double > dist(-1.0, 1.0);
  RandomGenerator< D > rand;

  const int m = 23;
  const int n = 40;
  const int k = 32;
  const int lda = 39;
  const int ldb = 47;
  const int ldc = 50;
  D a[m * lda], b[k * ldb], c[m * ldc], c_orig[m * ldc];
  D alpha = rand(&gen, &dist);
  D beta = rand(&gen, &dist);
  for (int i = 0; i < m * lda; ++i) {
    a[i] = rand(&gen, &dist);
  }
  for (int i = 0; i < k * ldb; ++i) {
    b[i] = rand(&gen, &dist);
  }
  for (int i = 0; i < m * ldc; ++i) {
    c[i] = rand(&gen, &dist);
    c_orig[i] = c[i];
  }
  cxxblas::gemm(m, n, k, a, b, c, alpha, beta, lda, ldb, ldc);

  D result = 0.0;
  for (int i = 0; i < m; ++i) {
    for (int j = 0; j < n; ++j) {
      result = 0.0;
      for (int p = 0; p < k; ++p) {
        result += a[i * lda + p] * b[p * ldb + j];
      }
      result = alpha * result + beta * c_orig[i * ldc + j];
      expectEq(result, c[i * ldc + j]);
    }
  }
}

TEST(CxxBlasTest, gemmTest) {
  gemmTest< double >();
  gemmTest< float >();
  gemmTest< ::std::complex< double > >();
  gemmTest< ::std::complex< float > >();
}

template < typename D >
void hemmTest() {
  ::std::random_device rd;
  ::std::mt19937 gen(rd());
  ::std::uniform_real_distribution< double > dist(-1.0, 1.0);
  RandomGenerator< D > rand;

  const int m = 23;
  const int n = 40;
  const int lda = 36;
  const int ldb = 47;
  const int ldc = 50;
  D a[m * lda], b[m * ldb], c[m * ldc], c_orig[m * ldc];
  D alpha = rand(&gen, &dist);
  D beta = rand(&gen, &dist);
  for (int i = 0; i < m * lda; ++i) {
    a[i] = rand(&gen, &dist);
  }
  for (int i = 0; i < m; ++i) {
    a[i * lda + i] = ::std::real(a[i * lda + i]);
  }
  for (int i = 0; i < m * ldb; ++i) {
    b[i] = rand(&gen, &dist);
  }
  for (int i = 0; i < m * ldc; ++i) {
    c[i] = rand(&gen, &dist);
    c_orig[i] = c[i];
  }
  cxxblas::hemm(m, n, a, b, c, alpha, beta, lda, ldb, ldc);

  D result = 0.0;
  for (int i = 0; i < m; ++i) {
    for (int j = 0; j < n; ++j) {
      result = 0.0;
      for (int p = 0; p < i; ++p) {
        // Lower: using a(i, p) = conj(a(p, i))
        result += conjg(a[p * lda + i]) * b[p * ldb + j];
      }
      for (int p = i; p < m; ++p) {
        // Upper: using a(i, p)
        result += a[i * lda + p] * b[p * ldb + j];
      }
      result = alpha * result + beta * c_orig[i * ldc + j];
      expectEq(result, c[i * ldc + j]);
    }
  }
}

TEST(CxxBlasTest, hemmTest) {
  hemmTest< double >();
  hemmTest< float >();
  hemmTest< ::std::complex< double > >();
  hemmTest< ::std::complex< float > >();
}

template < typename D >
void herkTest() {
  ::std::random_device rd;
  ::std::mt19937 gen(rd());
  ::std::uniform_real_distribution< double > dist(-1.0, 1.0);
  RandomGenerator< D > rand;

  const int n = 23;
  const int k = 15;
  const int lda = 18;
  const int ldc = 33;
  D a[n * lda], c[n * ldc], c_orig[n * ldc];
  D alpha = rand(&gen, &dist);
  D beta = rand(&gen, &dist);
  for (int i = 0; i < n * lda; ++i) {
    a[i] = rand(&gen, &dist);
  }
  for (int i = 0; i < n * ldc; ++i) {
    c[i] = rand(&gen, &dist);
    c_orig[i] = c[i];
  }
  for (int i = 0; i < n; ++i) {
    c[i * ldc + i] = ::std::real(c[i * ldc + i]);
    c_orig[i * ldc + i] = c[i * ldc + i];
  }
  cxxblas::herk(n, k, a, c, ::std::real(alpha), ::std::real(beta), lda, ldc);

  D result = 0.0;
  for (int i = 0; i < n; ++i) {
    for (int j = i; j < n; ++j) {
      result = 0.0;
      for (int p = 0; p < k; ++p) {
        result += a[i * lda + p] * conjg(a[j * lda + p]);
      }
      result = ::std::real(alpha) * result +
          ::std::real(beta) * c_orig[i * ldc + j];
      expectEq(result, c[i * ldc + j]);
    }
  }
}

TEST(CxxBlasTest, herkTest) {
  herkTest< double >();
  herkTest< float >();
  herkTest< ::std::complex< double > >();
  herkTest< ::std::complex< float > >();
}

template < typename D >
void her2kTest() {
  ::std::random_device rd;
  ::std::mt19937 gen(rd());
  ::std::uniform_real_distribution< double > dist(-1.0, 1.0);
  RandomGenerator< D > rand;

  const int n = 23;
  const int k = 15;
  const int lda = 18;
  const int ldb = 25;
  const int ldc = 33;
  D a[n * lda], b[n * ldb], c[n * ldc], c_orig[n * ldc];
  D alpha = rand(&gen, &dist);
  D beta = rand(&gen, &dist);
  for (int i = 0; i < n * lda; ++i) {
    a[i] = rand(&gen, &dist);
  }
  for (int i = 0; i < n * ldb; ++i) {
    b[i] = rand(&gen, &dist);
  }
  for (int i = 0; i < n * ldc; ++i) {
    c[i] = rand(&gen, &dist);
    c_orig[i] = c[i];
  }
  for (int i = 0; i < n; ++i) {
    c[i * ldc + i] = ::std::real(c[i * ldc + i]);
    c_orig[i * ldc + i] = c[i * ldc + i];
  }
  cxxblas::her2k(n, k, a, b, c, alpha, ::std::real(beta), lda, ldb, ldc);

  D result = 0.0;
  for (int i = 0; i < n; ++i) {
    for (int j = i; j < n; ++j) {
      result = 0.0;
      for (int p = 0; p < k; ++p) {
        result += alpha * a[i * lda + p] * conjg(b[j * ldb + p]) +
            conjg(alpha) * b[i * ldb + p] * conjg(a[j * lda + p]);
      }
      result = result + ::std::real(beta) * c_orig[i * ldc + j];
      expectEq(result, c[i * ldc + j]);
    }
  }
}

TEST(CxxBlasTest, her2kTest) {
  her2kTest< double >();
  her2kTest< float >();
  her2kTest< ::std::complex< double > >();
  her2kTest< ::std::complex< float > >();
}

}  // namespace
}  // namespace linalg
}  // namespace thunder
<commit_msg>Added tests for symm, syrk and syr2k<commit_after>/*
 * \copyright Copyright 2015 Xiang Zhang All Rights Reserved.
 * \license @{
 *
 * 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.
 *
 * @}
 */

/* Disclaimer: these tests are not complete. In particular, we do not test the
 * variants of order, transpose, uppper-lower, diagonal and side choices. We
 * always use row-major, no transpose, upper matrix, non-unit diagonal and left
 * side settings.
 */

#include <complex>
#include <cstdlib>
#include <random>

#include "gtest/gtest.h"
#include "thunder/linalg/cxxblas.hpp"

namespace thunder {
namespace linalg {
namespace {

template < typename D >
void expectEq(const D &a, const D &b) {
  EXPECT_FLOAT_EQ(a, b);
}
template < typename D >
void expectEq(const ::std::complex< D > &a, const ::std::complex< D > &b) {
  EXPECT_FLOAT_EQ(::std::real(a), ::std::real(b));
  EXPECT_FLOAT_EQ(::std::imag(a), ::std::imag(b));
}

template < typename D >
D conjg(const D &v) {
  return v;
}
template < typename D >
::std::complex< D > conjg(const ::std::complex< D > &v) {
  return ::std::conj(v);
}

template < typename D >
class RandomGenerator {
 public:
  template < typename G, typename R >
  D operator()(G *gen, R *dist) {
    return static_cast< D >((*dist)(*gen));
  }
};

template < typename D >
class RandomGenerator< ::std::complex< D > > {
 public:
  template < typename G, typename R >
  ::std::complex< D > operator()(G *gen, R *dist) {
    return ::std::complex< D >(
        static_cast< D >((*dist)(*gen)), static_cast< D >((*dist)(*gen)));
  }
};

template < typename D >
void gemmTest() {
  ::std::random_device rd;
  ::std::mt19937 gen(rd());
  ::std::uniform_real_distribution< double > dist(-1.0, 1.0);
  RandomGenerator< D > rand;

  const int m = 23;
  const int n = 40;
  const int k = 32;
  const int lda = 39;
  const int ldb = 47;
  const int ldc = 50;
  D a[m * lda], b[k * ldb], c[m * ldc], c_orig[m * ldc];
  D alpha = rand(&gen, &dist);
  D beta = rand(&gen, &dist);
  for (int i = 0; i < m * lda; ++i) {
    a[i] = rand(&gen, &dist);
  }
  for (int i = 0; i < k * ldb; ++i) {
    b[i] = rand(&gen, &dist);
  }
  for (int i = 0; i < m * ldc; ++i) {
    c[i] = rand(&gen, &dist);
    c_orig[i] = c[i];
  }
  cxxblas::gemm(m, n, k, a, b, c, alpha, beta, lda, ldb, ldc);

  D result = 0.0;
  for (int i = 0; i < m; ++i) {
    for (int j = 0; j < n; ++j) {
      result = 0.0;
      for (int p = 0; p < k; ++p) {
        result += a[i * lda + p] * b[p * ldb + j];
      }
      result = alpha * result + beta * c_orig[i * ldc + j];
      expectEq(result, c[i * ldc + j]);
    }
  }
}

TEST(CxxBlasTest, gemmTest) {
  gemmTest< double >();
  gemmTest< float >();
  gemmTest< ::std::complex< double > >();
  gemmTest< ::std::complex< float > >();
}

template < typename D >
void hemmTest() {
  ::std::random_device rd;
  ::std::mt19937 gen(rd());
  ::std::uniform_real_distribution< double > dist(-1.0, 1.0);
  RandomGenerator< D > rand;

  const int m = 23;
  const int n = 40;
  const int lda = 36;
  const int ldb = 47;
  const int ldc = 50;
  D a[m * lda], b[m * ldb], c[m * ldc], c_orig[m * ldc];
  D alpha = rand(&gen, &dist);
  D beta = rand(&gen, &dist);
  for (int i = 0; i < m * lda; ++i) {
    a[i] = rand(&gen, &dist);
  }
  for (int i = 0; i < m; ++i) {
    a[i * lda + i] = ::std::real(a[i * lda + i]);
  }
  for (int i = 0; i < m * ldb; ++i) {
    b[i] = rand(&gen, &dist);
  }
  for (int i = 0; i < m * ldc; ++i) {
    c[i] = rand(&gen, &dist);
    c_orig[i] = c[i];
  }
  cxxblas::hemm(m, n, a, b, c, alpha, beta, lda, ldb, ldc);

  D result = 0.0;
  for (int i = 0; i < m; ++i) {
    for (int j = 0; j < n; ++j) {
      result = 0.0;
      for (int p = 0; p < i; ++p) {
        // Lower: using a(i, p) = conj(a(p, i))
        result += conjg(a[p * lda + i]) * b[p * ldb + j];
      }
      for (int p = i; p < m; ++p) {
        // Upper: using a(i, p)
        result += a[i * lda + p] * b[p * ldb + j];
      }
      result = alpha * result + beta * c_orig[i * ldc + j];
      expectEq(result, c[i * ldc + j]);
    }
  }
}

TEST(CxxBlasTest, hemmTest) {
  hemmTest< double >();
  hemmTest< float >();
  hemmTest< ::std::complex< double > >();
  hemmTest< ::std::complex< float > >();
}

template < typename D >
void herkTest() {
  ::std::random_device rd;
  ::std::mt19937 gen(rd());
  ::std::uniform_real_distribution< double > dist(-1.0, 1.0);
  RandomGenerator< D > rand;

  const int n = 23;
  const int k = 15;
  const int lda = 18;
  const int ldc = 33;
  D a[n * lda], c[n * ldc], c_orig[n * ldc];
  D alpha = rand(&gen, &dist);
  D beta = rand(&gen, &dist);
  for (int i = 0; i < n * lda; ++i) {
    a[i] = rand(&gen, &dist);
  }
  for (int i = 0; i < n * ldc; ++i) {
    c[i] = rand(&gen, &dist);
    c_orig[i] = c[i];
  }
  for (int i = 0; i < n; ++i) {
    c[i * ldc + i] = ::std::real(c[i * ldc + i]);
    c_orig[i * ldc + i] = c[i * ldc + i];
  }
  cxxblas::herk(n, k, a, c, ::std::real(alpha), ::std::real(beta), lda, ldc);

  D result = 0.0;
  for (int i = 0; i < n; ++i) {
    for (int j = i; j < n; ++j) {
      result = 0.0;
      for (int p = 0; p < k; ++p) {
        result += a[i * lda + p] * conjg(a[j * lda + p]);
      }
      result = ::std::real(alpha) * result +
          ::std::real(beta) * c_orig[i * ldc + j];
      expectEq(result, c[i * ldc + j]);
    }
  }
}

TEST(CxxBlasTest, herkTest) {
  herkTest< double >();
  herkTest< float >();
  herkTest< ::std::complex< double > >();
  herkTest< ::std::complex< float > >();
}

template < typename D >
void her2kTest() {
  ::std::random_device rd;
  ::std::mt19937 gen(rd());
  ::std::uniform_real_distribution< double > dist(-1.0, 1.0);
  RandomGenerator< D > rand;

  const int n = 23;
  const int k = 15;
  const int lda = 18;
  const int ldb = 25;
  const int ldc = 33;
  D a[n * lda], b[n * ldb], c[n * ldc], c_orig[n * ldc];
  D alpha = rand(&gen, &dist);
  D beta = rand(&gen, &dist);
  for (int i = 0; i < n * lda; ++i) {
    a[i] = rand(&gen, &dist);
  }
  for (int i = 0; i < n * ldb; ++i) {
    b[i] = rand(&gen, &dist);
  }
  for (int i = 0; i < n * ldc; ++i) {
    c[i] = rand(&gen, &dist);
    c_orig[i] = c[i];
  }
  for (int i = 0; i < n; ++i) {
    c[i * ldc + i] = ::std::real(c[i * ldc + i]);
    c_orig[i * ldc + i] = c[i * ldc + i];
  }
  cxxblas::her2k(n, k, a, b, c, alpha, ::std::real(beta), lda, ldb, ldc);

  D result = 0.0;
  for (int i = 0; i < n; ++i) {
    for (int j = i; j < n; ++j) {
      result = 0.0;
      for (int p = 0; p < k; ++p) {
        result += alpha * a[i * lda + p] * conjg(b[j * ldb + p]) +
            conjg(alpha) * b[i * ldb + p] * conjg(a[j * lda + p]);
      }
      result = result + ::std::real(beta) * c_orig[i * ldc + j];
      expectEq(result, c[i * ldc + j]);
    }
  }
}

TEST(CxxBlasTest, her2kTest) {
  her2kTest< double >();
  her2kTest< float >();
  her2kTest< ::std::complex< double > >();
  her2kTest< ::std::complex< float > >();
}

template < typename D >
void symmTest() {
  ::std::random_device rd;
  ::std::mt19937 gen(rd());
  ::std::uniform_real_distribution< double > dist(-1.0, 1.0);
  RandomGenerator< D > rand;

  const int m = 23;
  const int n = 40;
  const int lda = 36;
  const int ldb = 47;
  const int ldc = 50;
  D a[m * lda], b[m * ldb], c[m * ldc], c_orig[m * ldc];
  D alpha = rand(&gen, &dist);
  D beta = rand(&gen, &dist);
  for (int i = 0; i < m * lda; ++i) {
    a[i] = rand(&gen, &dist);
  }
  for (int i = 0; i < m * ldb; ++i) {
    b[i] = rand(&gen, &dist);
  }
  for (int i = 0; i < m * ldc; ++i) {
    c[i] = rand(&gen, &dist);
    c_orig[i] = c[i];
  }
  cxxblas::symm(m, n, a, b, c, alpha, beta, lda, ldb, ldc);

  D result = 0.0;
  for (int i = 0; i < m; ++i) {
    for (int j = 0; j < n; ++j) {
      result = 0.0;
      for (int p = 0; p < i; ++p) {
        // Lower: using a(i, p) = a(p, i)
        result += a[p * lda + i] * b[p * ldb + j];
      }
      for (int p = i; p < m; ++p) {
        // Upper: using a(i, p)
        result += a[i * lda + p] * b[p * ldb + j];
      }
      result = alpha * result + beta * c_orig[i * ldc + j];
      expectEq(result, c[i * ldc + j]);
    }
  }
}

TEST(CxxBlasTest, symmTest) {
  symmTest< double >();
  symmTest< float >();
  symmTest< ::std::complex< double > >();
  symmTest< ::std::complex< float > >();
}

template < typename D >
void syrkTest() {
  ::std::random_device rd;
  ::std::mt19937 gen(rd());
  ::std::uniform_real_distribution< double > dist(-1.0, 1.0);
  RandomGenerator< D > rand;

  const int n = 23;
  const int k = 15;
  const int lda = 18;
  const int ldc = 33;
  D a[n * lda], c[n * ldc], c_orig[n * ldc];
  D alpha = rand(&gen, &dist);
  D beta = rand(&gen, &dist);
  for (int i = 0; i < n * lda; ++i) {
    a[i] = rand(&gen, &dist);
  }
  for (int i = 0; i < n * ldc; ++i) {
    c[i] = rand(&gen, &dist);
    c_orig[i] = c[i];
  }
  cxxblas::syrk(n, k, a, c, alpha, beta, lda, ldc);

  D result = 0.0;
  for (int i = 0; i < n; ++i) {
    for (int j = i; j < n; ++j) {
      result = 0.0;
      for (int p = 0; p < k; ++p) {
        result += a[i * lda + p] * a[j * lda + p];
      }
      result = alpha * result + beta * c_orig[i * ldc + j];
      expectEq(result, c[i * ldc + j]);
    }
  }
}

TEST(CxxBlasTest, syrkTest) {
  syrkTest< double >();
  syrkTest< float >();
  syrkTest< ::std::complex< double > >();
  syrkTest< ::std::complex< float > >();
}

template < typename D >
void syr2kTest() {
  ::std::random_device rd;
  ::std::mt19937 gen(rd());
  ::std::uniform_real_distribution< double > dist(-1.0, 1.0);
  RandomGenerator< D > rand;

  const int n = 23;
  const int k = 15;
  const int lda = 18;
  const int ldb = 25;
  const int ldc = 33;
  D a[n * lda], b[n * ldb], c[n * ldc], c_orig[n * ldc];
  D alpha = rand(&gen, &dist);
  D beta = rand(&gen, &dist);
  for (int i = 0; i < n * lda; ++i) {
    a[i] = rand(&gen, &dist);
  }
  for (int i = 0; i < n * ldb; ++i) {
    b[i] = rand(&gen, &dist);
  }
  for (int i = 0; i < n * ldc; ++i) {
    c[i] = rand(&gen, &dist);
    c_orig[i] = c[i];
  }
  cxxblas::syr2k(n, k, a, b, c, alpha, beta, lda, ldb, ldc);

  D result = 0.0;
  for (int i = 0; i < n; ++i) {
    for (int j = i; j < n; ++j) {
      result = 0.0;
      for (int p = 0; p < k; ++p) {
        result += a[i * lda + p] * b[j * ldb + p] +
            b[i * ldb + p] * a[j * lda + p];
      }
      result = alpha * result + beta * c_orig[i * ldc + j];
      expectEq(result, c[i * ldc + j]);
    }
  }
}

TEST(CxxBlasTest, syr2kTest) {
  syr2kTest< double >();
  syr2kTest< float >();
  syr2kTest< ::std::complex< double > >();
  syr2kTest< ::std::complex< float > >();
}

}  // namespace
}  // namespace linalg
}  // namespace thunder
<|endoftext|>


<commit_before>/*
 * File:  other_updates.cpp
 * Copyright (C) 2004 The Institute for System Programming of the Russian Academy of Sciences (ISP RAS)
 */

#include "common/sedna.h"

#include "tr/updates/updates.h"
#include "tr/executor/base/xptr_sequence.h"
#include "tr/mo/micro.h"
#include "tr/auth/auc.h"
#ifdef SE_ENABLE_TRIGGERS
#include "tr/triggers/triggers.h"
#endif
// Rename operation
void rename(PPOpIn arg,const char* name)
{
	// Creating the first sequence (different validity tests+ indirection deref)
	tuple t(arg.ts);
	xptr_sequence argseq;
	arg.op->next(t);
	while (!t.is_eos())
	{
		if (t.cells[0].is_node())
		{
			xptr node=t.cells[0].get_node();
			CHECKP(node);
			if (is_node_persistent(node)&& (is_node_element(node)||is_node_attribute(node)) )
			{
				//xptr indir=((n_dsc*)XADDR(node))->indir;
				argseq.add(node);
			}
#ifndef IGNORE_UPDATE_ERRORS
			else
			{
				throw USER_EXCEPTION(SE2020);
			}
#endif
		}
#ifndef IGNORE_UPDATE_ERRORS
			else
			{
				throw USER_EXCEPTION(SE2021);
			}
#endif
		arg.op->next(t);
	}

	if (argseq.size()<=0) return;
	// Checking authorization
	if (is_auth_check_needed(RENAME_STATEMENT))
		auth_for_update(&argseq, RENAME_STATEMENT, false);
	//Sort in document order
	argseq.sort();
	//changing to indirection
	xptr_sequence::iterator it=argseq.begin();
    xptr res;
	while (it!=argseq.end())
	{
		xptr node=*it;
		CHECKP(node);
		argseq.set(((n_dsc*)XADDR(node))->indir,it);
		++it;
	}
	it=argseq.end();
#ifdef SE_ENABLE_FTSEARCH
	clear_ft_sequences();
#endif
	do
	{
		--it;
		xptr indir=*it;
		xptr node=removeIndirection(indir);
		CHECKP(node);
		t_item type=GETTYPE((GETBLOCKBYNODE(node))->snode);
		n_dsc* desc=(n_dsc*)XADDR(node);
		xptr left=node;
		xptr parent=removeIndirection(desc->pdsc);
		CHECKP(node);
#ifdef SE_ENABLE_TRIGGERS
// add here triggers on RENAME !!!
//        if (apply_per_node_triggers(XNULL, XNULL, parent, TRIGGER_BEFORE, TRIGGER_INSERT_EVENT, name, type) == XNULL)
//    		return;
//        if (apply_per_node_triggers(XNULL, node, parent, TRIGGER_BEFORE, TRIGGER_DELETE_EVENT) == XNULL)
//    		return;
#endif

		switch(type)
		{
		case attribute:
			{
				//1. insert
				int size=((a_dsc*)desc)->size;
				if (size>0)
				{
					char *z=se_new char[size];
					xptr ind_ptr=((a_dsc*)desc)->data;
					CHECKP(ind_ptr);
					shft shift= *((shft*)XADDR(ind_ptr));
					char* data=(char*)XADDR(BLOCKXPTR(ind_ptr))+shift;
					memcpy(z,data,size);
					insert_attribute(left, XNULL, parent,name, ((a_dsc*)desc)->type,z,size,NULL);
					delete z;
				}
				else
					insert_attribute(left, XNULL, parent,name, ((a_dsc*)desc)->type,NULL,0,NULL);
				//2. delete
				CHECKP(indir);
				delete_node(*((xptr*)XADDR(indir)));
				break;
			}
		case element:
			{
				//1.INSERT
				res=insert_element(left, XNULL, parent,name,((e_dsc*)desc)->type,NULL);
				CHECKP(indir);
				copy_content(res,*((xptr*)XADDR(indir)),XNULL);
				//2.DELETE
				CHECKP(indir);
				delete_node(*((xptr*)XADDR(indir)));
				break;
			}
		}
#ifdef SE_ENABLE_TRIGGERS
        apply_per_node_triggers(res, XNULL, parent, NULL, TRIGGER_AFTER, TRIGGER_INSERT_EVENT);
#endif
		if (it==argseq.begin()) break;
	}
	while (true);
#ifdef SE_ENABLE_FTSEARCH
	execute_modifications();
#endif
}<commit_msg>upd-fix-2<commit_after>/*
 * File:  other_updates.cpp
 * Copyright (C) 2004 The Institute for System Programming of the Russian Academy of Sciences (ISP RAS)
 */

#include "common/sedna.h"

#include "tr/updates/updates.h"
#include "tr/executor/base/xptr_sequence.h"
#include "tr/mo/micro.h"
#include "tr/auth/auc.h"
#ifdef SE_ENABLE_TRIGGERS
#include "tr/triggers/triggers.h"
#endif
// Rename operation
void rename(PPOpIn arg,const char* name)
{
	// Creating the first sequence (different validity tests+ indirection deref)
	tuple t(arg.ts);
	xptr_sequence argseq;
	arg.op->next(t);
	while (!t.is_eos())
	{
		if (t.cells[0].is_node())
		{
			xptr node=t.cells[0].get_node();
			CHECKP(node);
			if (is_node_persistent(node)&& (is_node_element(node)||is_node_attribute(node)) )
			{
				//xptr indir=((n_dsc*)XADDR(node))->indir;
				argseq.add(node);
			}
#ifndef IGNORE_UPDATE_ERRORS
			else
			{
				throw USER_EXCEPTION(SE2020);
			}
#endif
		}
#ifndef IGNORE_UPDATE_ERRORS
			else
			{
				throw USER_EXCEPTION(SE2021);
			}
#endif
		arg.op->next(t);
	}

	if (argseq.size()<=0) return;
	// Checking authorization
	if (is_auth_check_needed(RENAME_STATEMENT))
		auth_for_update(&argseq, RENAME_STATEMENT, false);
	//Sort in document order
	argseq.sort();
	//changing to indirection
	xptr_sequence::iterator it=argseq.begin();
    xptr res;
	while (it!=argseq.end())
	{
		xptr node=*it;
		CHECKP(node);
		argseq.set(((n_dsc*)XADDR(node))->indir,it);
		++it;
	}
	it=argseq.end();
#ifdef SE_ENABLE_FTSEARCH
	clear_ft_sequences();
#endif
	do
	{
		--it;
		xptr indir=*it;
		xptr node=removeIndirection(indir);
		CHECKP(node);
		t_item type=GETTYPE((GETBLOCKBYNODE(node))->snode);
		n_dsc* desc=(n_dsc*)XADDR(node);
		xptr left=node;
		xptr parent=removeIndirection(desc->pdsc);
		CHECKP(node);
#ifdef SE_ENABLE_TRIGGERS
// add here triggers on RENAME !!!
//        if (apply_per_node_triggers(XNULL, XNULL, parent, TRIGGER_BEFORE, TRIGGER_INSERT_EVENT, name, type) == XNULL)
//    		return;
//        if (apply_per_node_triggers(XNULL, node, parent, TRIGGER_BEFORE, TRIGGER_DELETE_EVENT) == XNULL)
//    		return;
#endif

		switch(type)
		{
		case attribute:
			{
				//1. insert
				int size=((a_dsc*)desc)->size;
				if (size>0)
				{
					char *z=se_new char[size];
					xptr ind_ptr=((a_dsc*)desc)->data;
					CHECKP(ind_ptr);
					shft shift= *((shft*)XADDR(ind_ptr));
					char* data=(char*)XADDR(BLOCKXPTR(ind_ptr))+shift;
					memcpy(z,data,size);
					res=insert_attribute(left, XNULL, parent,name, ((a_dsc*)desc)->type,z,size,NULL);
					delete z;
				}
				else
					res=insert_attribute(left, XNULL, parent,name, ((a_dsc*)desc)->type,NULL,0,NULL);
				//2. delete
				CHECKP(indir);
				delete_node(*((xptr*)XADDR(indir)));
				break;
			}
		case element:
			{
				//1.INSERT
				res=insert_element(left, XNULL, parent,name,((e_dsc*)desc)->type,NULL);
				CHECKP(indir);
				copy_content(res,*((xptr*)XADDR(indir)),XNULL);
				//2.DELETE
				CHECKP(indir);
				delete_node(*((xptr*)XADDR(indir)));
				break;
			}
		}
#ifdef SE_ENABLE_TRIGGERS
        apply_per_node_triggers(res, XNULL, parent, NULL, TRIGGER_AFTER, TRIGGER_INSERT_EVENT);
#endif
		if (it==argseq.begin()) break;
	}
	while (true);
#ifdef SE_ENABLE_FTSEARCH
	execute_modifications();
#endif
}<|endoftext|>


<commit_before>// Copyright (C) 2010 - 2016 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

// Copyright (C) 2009 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

#include <QtGui/QComboBox>
#include <QtGui/QSortFilterProxyModel>

#include "CQComboDelegate.h"

#include "copasi.h"

CQComboDelegate::CQComboDelegate(QObject *parent, const QStringList & comboItems, bool commitOnSelect):
  QItemDelegate(parent),
  mEditorToIndex(),
  mRowToItems(),
  mCommitOnSelect(commitOnSelect)
{
  mRowToItems[-1] = comboItems;
}

CQComboDelegate::~CQComboDelegate()
{}

QWidget *CQComboDelegate::createEditor(QWidget *parent,
                                       const QStyleOptionViewItem & C_UNUSED(option),
                                       const QModelIndex & index) const
{
  QModelIndex  SourceIndex = index;
  const QAbstractItemModel *pModel = index.model();

  while (pModel->inherits("QSortFilterProxyModel"))
    {
      SourceIndex = static_cast< const QSortFilterProxyModel *>(pModel)->mapToSource(SourceIndex);
      pModel = SourceIndex.model();
    }

  QComboBox *pEditor = new QComboBox(parent);
  mEditorToIndex[pEditor] = SourceIndex;

  pEditor->setAutoFillBackground(true);

  if (!getItems(SourceIndex).empty())
    {
      pEditor->addItems(getItems(SourceIndex));
    }

  connect(pEditor, SIGNAL(currentIndexChanged(int)), this, SLOT(slotCurrentIndexChanged(int)));
  connect(pEditor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDeleted(QObject *)));

  return pEditor;
}

void CQComboDelegate::setEditorData(QWidget *editor,
                                    const QModelIndex &index) const
{
  QString value = index.model()->data(index, Qt::DisplayRole).toString();
  QComboBox *comboBox = static_cast<QComboBox*>(editor);

  comboBox->blockSignals(true);
  comboBox->setCurrentIndex(comboBox->findText(value));
  comboBox->blockSignals(false);
}

void CQComboDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
                                   const QModelIndex &index) const
{
  QComboBox *comboBox = static_cast<QComboBox*>(editor);
  QVariant value(comboBox->currentText());
  QVariant current = model->data(index, Qt::EditRole);

  if (value != current)
    model->setData(index, value, Qt::EditRole);
}

void CQComboDelegate::updateEditorGeometry(QWidget *pEditor, const QStyleOptionViewItem &option,
    const QModelIndex & /* index */) const
{
  QRect Rectangle = option.rect;
  Rectangle.setRight(Rectangle.left() + std::min(Rectangle.width(), std::max(pEditor->sizeHint().width(), Rectangle.height())));
  Rectangle.setBottom(Rectangle.top() + std::max(pEditor->sizeHint().height(), Rectangle.height()));
  pEditor->setGeometry(Rectangle);
}

void CQComboDelegate::setItems(int row, const QStringList & comboItems)
{
  mRowToItems[row] = comboItems;
}

QStringList CQComboDelegate::getItems(const QModelIndex & index) const
{
  if (!mRowToItems[-1].empty())
    {
      return mRowToItems[-1];
    }

  QMap< int, QStringList >::const_iterator found = mRowToItems.find(index.row());

  if (found != mRowToItems.end()) // OK to return found.value() = NULL
    {
      return found.value();
    }

  return index.model()->data(index, Qt::UserRole).toStringList();
}

void CQComboDelegate::slotCurrentIndexChanged(int index)
{
  QComboBox * pEditor = dynamic_cast< QComboBox * >(sender());

  if (pEditor)
    {
      QMap< QWidget * , QModelIndex >::const_iterator found = mEditorToIndex.find(pEditor);

      if (found != mEditorToIndex.end())
        {
          emit currentIndexChanged(found.value().row(), index);

          if (mCommitOnSelect)
            commitData(pEditor);
        }
    }
}

void CQComboDelegate::slotEditorDeleted(QObject * pObject)
{
  mEditorToIndex.remove(static_cast< QWidget * >(pObject));
}

bool CQComboDelegate::isCommitOnSelect() const
{
  return mCommitOnSelect;
}

QSize CQComboDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const
{
  QModelIndex  SourceIndex = index;
  const QAbstractItemModel *pModel = index.model();

  while (pModel->inherits("QSortFilterProxyModel"))
    {
      SourceIndex = static_cast< const QSortFilterProxyModel *>(pModel)->mapToSource(SourceIndex);
      pModel = SourceIndex.model();
    }

  QWidget * pEditor = mEditorToIndex.key(SourceIndex, NULL);

  if (pEditor != NULL)
    return pEditor->sizeHint();

  QComboBox *pTmp = new QComboBox();

  pTmp->setAutoFillBackground(true);

  if (!getItems(SourceIndex).empty())
    {
      pTmp->addItems(getItems(SourceIndex));
    }

  QSize SizeHint = pTmp->sizeHint();

  delete pTmp;

  return SizeHint; // QItemDelegate::sizeHint(option, index);
}

void CQComboDelegate::setCommitOnSelect(bool commitOnSelect)
{
  mCommitOnSelect = commitOnSelect;
}

CQIndexComboDelegate::CQIndexComboDelegate(QObject *parent, const QStringList & comboItems, bool commitOnSelect)
  : CQComboDelegate(parent, comboItems, commitOnSelect)
{}

CQIndexComboDelegate::~CQIndexComboDelegate()
{}

void CQIndexComboDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
                                        const QModelIndex &index) const
{
  QComboBox *comboBox = static_cast<QComboBox*>(editor);
  QVariant value(comboBox->currentIndex());
  model->setData(index, value, Qt::EditRole);
}
<commit_msg>- avoid crash and needless commit<commit_after>// Copyright (C) 2010 - 2016 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

// Copyright (C) 2009 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., EML Research, gGmbH, University of Heidelberg,
// and The University of Manchester.
// All rights reserved.

#include <QtGui/QComboBox>
#include <QtGui/QSortFilterProxyModel>

#include "CQComboDelegate.h"

#include "copasi.h"

CQComboDelegate::CQComboDelegate(QObject *parent, const QStringList & comboItems, bool commitOnSelect):
  QItemDelegate(parent),
  mEditorToIndex(),
  mRowToItems(),
  mCommitOnSelect(commitOnSelect)
{
  mRowToItems[-1] = comboItems;
}

CQComboDelegate::~CQComboDelegate()
{}

QWidget *CQComboDelegate::createEditor(QWidget *parent,
                                       const QStyleOptionViewItem & C_UNUSED(option),
                                       const QModelIndex & index) const
{
  QModelIndex  SourceIndex = index;
  const QAbstractItemModel *pModel = index.model();

  while (pModel->inherits("QSortFilterProxyModel"))
    {
      SourceIndex = static_cast< const QSortFilterProxyModel *>(pModel)->mapToSource(SourceIndex);
      pModel = SourceIndex.model();
    }

  QComboBox *pEditor = new QComboBox(parent);
  mEditorToIndex[pEditor] = SourceIndex;

  pEditor->setAutoFillBackground(true);

  if (!getItems(SourceIndex).empty())
    {
      pEditor->addItems(getItems(SourceIndex));
    }

  connect(pEditor, SIGNAL(currentIndexChanged(int)), this, SLOT(slotCurrentIndexChanged(int)));
  connect(pEditor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDeleted(QObject *)));

  return pEditor;
}

void CQComboDelegate::setEditorData(QWidget *editor,
                                    const QModelIndex &index) const
{
  QString value = index.model()->data(index, Qt::DisplayRole).toString();
  QComboBox *comboBox = static_cast<QComboBox*>(editor);

  comboBox->blockSignals(true);
  comboBox->setCurrentIndex(comboBox->findText(value));
  comboBox->blockSignals(false);
}

void CQComboDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
                                   const QModelIndex &index) const
{
  QComboBox *comboBox = static_cast<QComboBox*>(editor);
  QVariant value(comboBox->currentText());
  QVariant current = model->data(index, Qt::EditRole);

  if (value != current && model->rowCount() > 0)
    model->setData(index, value, Qt::EditRole);
}

void CQComboDelegate::updateEditorGeometry(QWidget *pEditor, const QStyleOptionViewItem &option,
    const QModelIndex & /* index */) const
{
  QRect Rectangle = option.rect;
  Rectangle.setRight(Rectangle.left() + std::min(Rectangle.width(), std::max(pEditor->sizeHint().width(), Rectangle.height())));
  Rectangle.setBottom(Rectangle.top() + std::max(pEditor->sizeHint().height(), Rectangle.height()));
  pEditor->setGeometry(Rectangle);
}

void CQComboDelegate::setItems(int row, const QStringList & comboItems)
{
  mRowToItems[row] = comboItems;
}

QStringList CQComboDelegate::getItems(const QModelIndex & index) const
{
  if (!mRowToItems[-1].empty())
    {
      return mRowToItems[-1];
    }

  QMap< int, QStringList >::const_iterator found = mRowToItems.find(index.row());

  if (found != mRowToItems.end()) // OK to return found.value() = NULL
    {
      return found.value();
    }

  return index.model()->data(index, Qt::UserRole).toStringList();
}

void CQComboDelegate::slotCurrentIndexChanged(int index)
{
  QComboBox * pEditor = dynamic_cast< QComboBox * >(sender());

  if (pEditor)
    {
      QMap< QWidget * , QModelIndex >::const_iterator found = mEditorToIndex.find(pEditor);

      if (found != mEditorToIndex.end())
        {
          emit currentIndexChanged(found.value().row(), index);

          if (mCommitOnSelect)
            commitData(pEditor);
        }
    }
}

void CQComboDelegate::slotEditorDeleted(QObject * pObject)
{
  mEditorToIndex.remove(static_cast< QWidget * >(pObject));
}

bool CQComboDelegate::isCommitOnSelect() const
{
  return mCommitOnSelect;
}

QSize CQComboDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const
{
  QModelIndex  SourceIndex = index;
  const QAbstractItemModel *pModel = index.model();

  while (pModel != NULL && pModel->inherits("QSortFilterProxyModel"))
    {
      SourceIndex = static_cast< const QSortFilterProxyModel *>(pModel)->mapToSource(SourceIndex);
      pModel = SourceIndex.model();
    }

  QWidget * pEditor = mEditorToIndex.key(SourceIndex, NULL);

  if (pEditor != NULL)
    return pEditor->sizeHint();

  QComboBox *pTmp = new QComboBox();

  pTmp->setAutoFillBackground(true);

  if (!getItems(SourceIndex).empty())
    {
      pTmp->addItems(getItems(SourceIndex));
    }

  QSize SizeHint = pTmp->sizeHint();

  delete pTmp;

  return SizeHint; // QItemDelegate::sizeHint(option, index);
}

void CQComboDelegate::setCommitOnSelect(bool commitOnSelect)
{
  mCommitOnSelect = commitOnSelect;
}

CQIndexComboDelegate::CQIndexComboDelegate(QObject *parent, const QStringList & comboItems, bool commitOnSelect)
  : CQComboDelegate(parent, comboItems, commitOnSelect)
{}

CQIndexComboDelegate::~CQIndexComboDelegate()
{}

void CQIndexComboDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
                                        const QModelIndex &index) const
{
  QComboBox *comboBox = static_cast<QComboBox*>(editor);
  QVariant value(comboBox->currentIndex());

  if (model->data(index, Qt::EditRole) != value)
    model->setData(index, value, Qt::EditRole);
}
<|endoftext|>


<commit_before>/* Copyright 2017 Stanford University
 *
 * 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 "stencil_mapper.h"

#include "default_mapper.h"

#define SPMD_SHARD_USE_IO_PROC 1

using namespace Legion;
using namespace Legion::Mapping;

static LegionRuntime::Logger::Category log_stencil("stencil");

class StencilMapper : public DefaultMapper
{
public:
  StencilMapper(MapperRuntime *rt, Machine machine, Processor local,
                const char *mapper_name,
                std::vector<Processor>* procs_list,
                std::vector<Memory>* sysmems_list,
                std::map<Memory, std::vector<Processor> >* sysmem_local_procs,
#if SPMD_SHARD_USE_IO_PROC
                std::map<Memory, std::vector<Processor> >* sysmem_local_io_procs,
#endif
                std::map<Processor, Memory>* proc_sysmems,
                std::map<Processor, Memory>* proc_regmems);
  virtual void select_task_options(const MapperContext    ctx,
                                   const Task&            task,
                                         TaskOptions&     output);
  virtual void default_policy_rank_processor_kinds(
                                    MapperContext ctx, const Task &task,
                                    std::vector<Processor::Kind> &ranking);
  virtual Processor default_policy_select_initial_processor(
                                    MapperContext ctx, const Task &task);
  virtual void default_policy_select_target_processors(
                                    MapperContext ctx,
                                    const Task &task,
                                    std::vector<Processor> &target_procs);
  virtual void map_copy(const MapperContext ctx,
                        const Copy &copy,
                        const MapCopyInput &input,
                        MapCopyOutput &output);
  template<bool IS_SRC>
  void stencil_create_copy_instance(MapperContext ctx, const Copy &copy,
                                    const RegionRequirement &req, unsigned index,
                                    std::vector<PhysicalInstance> &instances);
private:
  std::vector<Processor>& procs_list;
  // std::vector<Memory>& sysmems_list;
  std::map<Memory, std::vector<Processor> >& sysmem_local_procs;
#if SPMD_SHARD_USE_IO_PROC
  std::map<Memory, std::vector<Processor> >& sysmem_local_io_procs;
#endif
  // std::map<Processor, Memory>& proc_sysmems;
  // std::map<Processor, Memory>& proc_regmems;
};

StencilMapper::StencilMapper(MapperRuntime *rt, Machine machine, Processor local,
                             const char *mapper_name,
                             std::vector<Processor>* _procs_list,
                             std::vector<Memory>* _sysmems_list,
                             std::map<Memory, std::vector<Processor> >* _sysmem_local_procs,
#if SPMD_SHARD_USE_IO_PROC
                             std::map<Memory, std::vector<Processor> >* _sysmem_local_io_procs,
#endif
                             std::map<Processor, Memory>* _proc_sysmems,
                             std::map<Processor, Memory>* _proc_regmems)
  : DefaultMapper(rt, machine, local, mapper_name)
  , procs_list(*_procs_list)
  // , sysmems_list(*_sysmems_list)
  , sysmem_local_procs(*_sysmem_local_procs)
#if SPMD_SHARD_USE_IO_PROC
  , sysmem_local_io_procs(*_sysmem_local_io_procs)
#endif
  // , proc_sysmems(*_proc_sysmems)
  // , proc_regmems(*_proc_regmems)
{
}

void StencilMapper::select_task_options(const MapperContext    ctx,
                                        const Task&            task,
                                              TaskOptions&     output)
{
  output.initial_proc = default_policy_select_initial_processor(ctx, task);
  output.inline_task = false;
  output.stealable = stealing_enabled;
#ifdef MAP_LOCALLY
  output.map_locally = true;
#else
  output.map_locally = false;
#endif
}

void StencilMapper::default_policy_rank_processor_kinds(MapperContext ctx,
                        const Task &task, std::vector<Processor::Kind> &ranking)
{
#if SPMD_SHARD_USE_IO_PROC
  const char* task_name = task.get_task_name();
  const char* prefix = "shard_";
  if (strncmp(task_name, prefix, strlen(prefix)) == 0) {
    // Put shard tasks on IO processors.
    ranking.resize(4);
    ranking[0] = Processor::TOC_PROC;
    ranking[1] = Processor::PROC_SET;
    ranking[2] = Processor::IO_PROC;
    ranking[3] = Processor::LOC_PROC;
  } else {
#endif
    ranking.resize(4);
    ranking[0] = Processor::TOC_PROC;
    ranking[1] = Processor::PROC_SET;
    ranking[2] = Processor::LOC_PROC;
    ranking[3] = Processor::IO_PROC;
#if SPMD_SHARD_USE_IO_PROC
  }
#endif
}

Processor StencilMapper::default_policy_select_initial_processor(
                                    MapperContext ctx, const Task &task)
{
  return DefaultMapper::default_policy_select_initial_processor(ctx, task);
}

void StencilMapper::default_policy_select_target_processors(
                                    MapperContext ctx,
                                    const Task &task,
                                    std::vector<Processor> &target_procs)
{
  target_procs.push_back(task.target_proc);
}

void StencilMapper::map_copy(const MapperContext ctx,
                             const Copy &copy,
                             const MapCopyInput &input,
                             MapCopyOutput &output)
{
  log_stencil.spew("Stencil mapper map_copy");
  for (unsigned idx = 0; idx < copy.src_requirements.size(); idx++)
  {
    // Always use a virtual instance for the source.
    output.src_instances[idx].clear();
    output.src_instances[idx].push_back(
      PhysicalInstance::get_virtual_instance());

    // Place the destination instance on the remote node.
    output.dst_instances[idx].clear();
    if (!copy.dst_requirements[idx].is_restricted()) {
      // Call a customized method to create an instance on the desired node.
      stencil_create_copy_instance<false/*is src*/>(ctx, copy,
        copy.dst_requirements[idx], idx, output.dst_instances[idx]);
    } else {
      // If it's restricted, just take the instance. This will only
      // happen inside the shard task.
      output.dst_instances[idx] = input.dst_instances[idx];
      if (!output.dst_instances[idx].empty())
        runtime->acquire_and_filter_instances(ctx,
                                output.dst_instances[idx]);
    }
  }
}

//--------------------------------------------------------------------------
template<bool IS_SRC>
void StencilMapper::stencil_create_copy_instance(MapperContext ctx,
                     const Copy &copy, const RegionRequirement &req,
                     unsigned idx, std::vector<PhysicalInstance> &instances)
//--------------------------------------------------------------------------
{
  // This method is identical to the default version except that it
  // chooses an intelligent memory based on the destination of the
  // copy.

  // See if we have all the fields covered
  std::set<FieldID> missing_fields = req.privilege_fields;
  for (std::vector<PhysicalInstance>::const_iterator it =
        instances.begin(); it != instances.end(); it++)
  {
    it->remove_space_fields(missing_fields);
    if (missing_fields.empty())
      break;
  }
  if (missing_fields.empty())
    return;
  // If we still have fields, we need to make an instance
  // We clearly need to take a guess, let's see if we can find
  // one of our instances to use.

  // ELLIOTT: Get the remote node here.
  Color index = runtime->get_logical_region_color(ctx, copy.src_requirements[idx].region);
  Memory target_memory = default_policy_select_target_memory(ctx,
                           procs_list[index % procs_list.size()]);
  log_stencil.warning("Building instance for copy of a region with index %u to be in memory %llx",
                      index, target_memory.id);
  bool force_new_instances = false;
  LayoutConstraintID our_layout_id =
   default_policy_select_layout_constraints(ctx, target_memory,
                                            req, COPY_MAPPING,
                                            true/*needs check*/,
                                            force_new_instances);
  LayoutConstraintSet creation_constraints =
              runtime->find_layout_constraints(ctx, our_layout_id);
  creation_constraints.add_constraint(
      FieldConstraint(missing_fields,
                      false/*contig*/, false/*inorder*/));
  instances.resize(instances.size() + 1);
  if (!default_make_instance(ctx, target_memory,
        creation_constraints, instances.back(),
        COPY_MAPPING, force_new_instances, true/*meets*/, req))
  {
    // If we failed to make it that is bad
    log_stencil.error("Stencil mapper failed allocation for "
                   "%s region requirement %d of explicit "
                   "region-to-region copy operation in task %s "
                   "(ID %lld) in memory " IDFMT " for processor "
                   IDFMT ". This means the working set of your "
                   "application is too big for the allotted "
                   "capacity of the given memory under the default "
                   "mapper's mapping scheme. You have three "
                   "choices: ask Realm to allocate more memory, "
                   "write a custom mapper to better manage working "
                   "sets, or find a bigger machine. Good luck!",
                   IS_SRC ? "source" : "destination", idx,
                   copy.parent_task->get_task_name(),
                   copy.parent_task->get_unique_id(),
		       target_memory.id,
		       copy.parent_task->current_proc.id);
    assert(false);
  }
}

static void create_mappers(Machine machine, HighLevelRuntime *runtime, const std::set<Processor> &local_procs)
{
  std::vector<Processor>* procs_list = new std::vector<Processor>();
  std::vector<Memory>* sysmems_list = new std::vector<Memory>();
  std::map<Memory, std::vector<Processor> >* sysmem_local_procs =
    new std::map<Memory, std::vector<Processor> >();
#if SPMD_SHARD_USE_IO_PROC
  std::map<Memory, std::vector<Processor> >* sysmem_local_io_procs =
    new std::map<Memory, std::vector<Processor> >();
#endif
  std::map<Processor, Memory>* proc_sysmems = new std::map<Processor, Memory>();
  std::map<Processor, Memory>* proc_regmems = new std::map<Processor, Memory>();

  std::vector<Machine::ProcessorMemoryAffinity> proc_mem_affinities;
  machine.get_proc_mem_affinity(proc_mem_affinities);

  for (unsigned idx = 0; idx < proc_mem_affinities.size(); ++idx) {
    Machine::ProcessorMemoryAffinity& affinity = proc_mem_affinities[idx];
    if (affinity.p.kind() == Processor::LOC_PROC) {
      if (affinity.m.kind() == Memory::SYSTEM_MEM) {
        (*proc_sysmems)[affinity.p] = affinity.m;
        if (proc_regmems->find(affinity.p) == proc_regmems->end())
          (*proc_regmems)[affinity.p] = affinity.m;
      }
      else if (affinity.m.kind() == Memory::REGDMA_MEM)
        (*proc_regmems)[affinity.p] = affinity.m;
    }
  }

  for (std::map<Processor, Memory>::iterator it = proc_sysmems->begin();
       it != proc_sysmems->end(); ++it) {
    if (it->first.kind() == Processor::LOC_PROC) {
      procs_list->push_back(it->first);
      (*sysmem_local_procs)[it->second].push_back(it->first);
    }
#if SPMD_SHARD_USE_IO_PROC
    else if (it->first.kind() == Processor::IO_PROC) {
      (*sysmem_local_io_procs)[it->second].push_back(it->first);
    }
#endif
  }

  for (std::map<Memory, std::vector<Processor> >::iterator it =
        sysmem_local_procs->begin(); it != sysmem_local_procs->end(); ++it)
    sysmems_list->push_back(it->first);

  for (std::set<Processor>::const_iterator it = local_procs.begin();
        it != local_procs.end(); it++)
  {
    StencilMapper* mapper = new StencilMapper(runtime->get_mapper_runtime(),
                                              machine, *it, "stencil_mapper",
                                              procs_list,
                                              sysmems_list,
                                              sysmem_local_procs,
#if SPMD_SHARD_USE_IO_PROC
                                              sysmem_local_io_procs,
#endif
                                              proc_sysmems,
                                              proc_regmems);
    runtime->replace_default_mapper(mapper, *it);
  }
}

void register_mappers()
{
  HighLevelRuntime::add_registration_callback(create_mappers);
}
<commit_msg>regent: Update Stencil mapper to optimize map_task.<commit_after>/* Copyright 2017 Stanford University
 *
 * 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 "stencil_mapper.h"

#include "default_mapper.h"

#define SPMD_SHARD_USE_IO_PROC 1

using namespace Legion;
using namespace Legion::Mapping;

static LegionRuntime::Logger::Category log_stencil("stencil");

class StencilMapper : public DefaultMapper
{
public:
  StencilMapper(MapperRuntime *rt, Machine machine, Processor local,
                const char *mapper_name,
                std::vector<Processor>* procs_list,
                std::vector<Memory>* sysmems_list,
                std::map<Memory, std::vector<Processor> >* sysmem_local_procs,
#if SPMD_SHARD_USE_IO_PROC
                std::map<Memory, std::vector<Processor> >* sysmem_local_io_procs,
#endif
                std::map<Processor, Memory>* proc_sysmems,
                std::map<Processor, Memory>* proc_regmems);
  virtual void select_task_options(const MapperContext    ctx,
                                   const Task&            task,
                                         TaskOptions&     output);
  virtual void default_policy_rank_processor_kinds(
                                    MapperContext ctx, const Task &task,
                                    std::vector<Processor::Kind> &ranking);
  virtual Processor default_policy_select_initial_processor(
                                    MapperContext ctx, const Task &task);
  virtual void default_policy_select_target_processors(
                                    MapperContext ctx,
                                    const Task &task,
                                    std::vector<Processor> &target_procs);
  virtual LogicalRegion default_policy_select_instance_region(
                                MapperContext ctx, Memory target_memory,
                                const RegionRequirement &req,
                                const LayoutConstraintSet &constraints,
                                bool force_new_instances,
                                bool meets_constraints);
  virtual void map_task(const MapperContext ctx,
                        const Task &task,
                        const MapTaskInput &input,
                        MapTaskOutput &output);
  virtual void map_copy(const MapperContext ctx,
                        const Copy &copy,
                        const MapCopyInput &input,
                        MapCopyOutput &output);
  template<bool IS_SRC>
  void stencil_create_copy_instance(MapperContext ctx, const Copy &copy,
                                    const RegionRequirement &req, unsigned index,
                                    std::vector<PhysicalInstance> &instances);
private:
  std::vector<Processor>& procs_list;
  // std::vector<Memory>& sysmems_list;
  std::map<Memory, std::vector<Processor> >& sysmem_local_procs;
#if SPMD_SHARD_USE_IO_PROC
  std::map<Memory, std::vector<Processor> >& sysmem_local_io_procs;
#endif
  // std::map<Processor, Memory>& proc_sysmems;
  // std::map<Processor, Memory>& proc_regmems;
};

StencilMapper::StencilMapper(MapperRuntime *rt, Machine machine, Processor local,
                             const char *mapper_name,
                             std::vector<Processor>* _procs_list,
                             std::vector<Memory>* _sysmems_list,
                             std::map<Memory, std::vector<Processor> >* _sysmem_local_procs,
#if SPMD_SHARD_USE_IO_PROC
                             std::map<Memory, std::vector<Processor> >* _sysmem_local_io_procs,
#endif
                             std::map<Processor, Memory>* _proc_sysmems,
                             std::map<Processor, Memory>* _proc_regmems)
  : DefaultMapper(rt, machine, local, mapper_name)
  , procs_list(*_procs_list)
  // , sysmems_list(*_sysmems_list)
  , sysmem_local_procs(*_sysmem_local_procs)
#if SPMD_SHARD_USE_IO_PROC
  , sysmem_local_io_procs(*_sysmem_local_io_procs)
#endif
  // , proc_sysmems(*_proc_sysmems)
  // , proc_regmems(*_proc_regmems)
{
}

void StencilMapper::select_task_options(const MapperContext    ctx,
                                        const Task&            task,
                                              TaskOptions&     output)
{
  output.initial_proc = default_policy_select_initial_processor(ctx, task);
  output.inline_task = false;
  output.stealable = stealing_enabled;
#ifdef MAP_LOCALLY
  output.map_locally = true;
#else
  output.map_locally = false;
#endif
}

void StencilMapper::default_policy_rank_processor_kinds(MapperContext ctx,
                        const Task &task, std::vector<Processor::Kind> &ranking)
{
#if SPMD_SHARD_USE_IO_PROC
  const char* task_name = task.get_task_name();
  const char* prefix = "shard_";
  if (strncmp(task_name, prefix, strlen(prefix)) == 0) {
    // Put shard tasks on IO processors.
    ranking.resize(4);
    ranking[0] = Processor::TOC_PROC;
    ranking[1] = Processor::PROC_SET;
    ranking[2] = Processor::IO_PROC;
    ranking[3] = Processor::LOC_PROC;
  } else {
#endif
    ranking.resize(4);
    ranking[0] = Processor::TOC_PROC;
    ranking[1] = Processor::PROC_SET;
    ranking[2] = Processor::LOC_PROC;
    ranking[3] = Processor::IO_PROC;
#if SPMD_SHARD_USE_IO_PROC
  }
#endif
}

Processor StencilMapper::default_policy_select_initial_processor(
                                    MapperContext ctx, const Task &task)
{
  return DefaultMapper::default_policy_select_initial_processor(ctx, task);
}

void StencilMapper::default_policy_select_target_processors(
                                    MapperContext ctx,
                                    const Task &task,
                                    std::vector<Processor> &target_procs)
{
  target_procs.push_back(task.target_proc);
}

LogicalRegion StencilMapper::default_policy_select_instance_region(
                              MapperContext ctx, Memory target_memory,
                              const RegionRequirement &req,
                              const LayoutConstraintSet &constraints,
                              bool force_new_instances,
                              bool meets_constraints)
{
  return req.region;
}

void StencilMapper::map_task(const MapperContext      ctx,
                             const Task&              task,
                             const MapTaskInput&      input,
                                   MapTaskOutput&     output)
{
  if (task.parent_task != NULL && task.parent_task->must_epoch_task) {
    Processor::Kind target_kind = task.target_proc.kind();
    // Get the variant that we are going to use to map this task
    VariantInfo chosen = default_find_preferred_variant(task, ctx,
                                                        true/*needs tight bound*/, true/*cache*/, target_kind);
    output.chosen_variant = chosen.variant;
    // TODO: some criticality analysis to assign priorities
    output.task_priority = 0;
    output.postmap_task = false;
    // Figure out our target processors
    output.target_procs.push_back(task.target_proc);

    for (unsigned idx = 0; idx < task.regions.size(); idx++) {
      const RegionRequirement &req = task.regions[idx];

      // Skip any empty regions
      if ((req.privilege == NO_ACCESS) || (req.privilege_fields.empty()))
        continue;

      assert(input.valid_instances[idx].size() == 1);
      output.chosen_instances[idx] = input.valid_instances[idx];
      bool ok = runtime->acquire_and_filter_instances(ctx, output.chosen_instances);
      if (!ok) {
        log_stencil.error("failed to acquire instances");
        assert(false);
      }
    }
    return;
  }

  DefaultMapper::map_task(ctx, task, input, output);
}

void StencilMapper::map_copy(const MapperContext ctx,
                             const Copy &copy,
                             const MapCopyInput &input,
                             MapCopyOutput &output)
{
  log_stencil.spew("Stencil mapper map_copy");
  for (unsigned idx = 0; idx < copy.src_requirements.size(); idx++)
  {
    // Always use a virtual instance for the source.
    output.src_instances[idx].clear();
    output.src_instances[idx].push_back(
      PhysicalInstance::get_virtual_instance());

    // Place the destination instance on the remote node.
    output.dst_instances[idx].clear();
    if (!copy.dst_requirements[idx].is_restricted()) {
      // Call a customized method to create an instance on the desired node.
      stencil_create_copy_instance<false/*is src*/>(ctx, copy,
        copy.dst_requirements[idx], idx, output.dst_instances[idx]);
    } else {
      // If it's restricted, just take the instance. This will only
      // happen inside the shard task.
      output.dst_instances[idx] = input.dst_instances[idx];
      if (!output.dst_instances[idx].empty())
        runtime->acquire_and_filter_instances(ctx,
                                output.dst_instances[idx]);
    }
  }
}

//--------------------------------------------------------------------------
template<bool IS_SRC>
void StencilMapper::stencil_create_copy_instance(MapperContext ctx,
                     const Copy &copy, const RegionRequirement &req,
                     unsigned idx, std::vector<PhysicalInstance> &instances)
//--------------------------------------------------------------------------
{
  // This method is identical to the default version except that it
  // chooses an intelligent memory based on the destination of the
  // copy.

  // See if we have all the fields covered
  std::set<FieldID> missing_fields = req.privilege_fields;
  for (std::vector<PhysicalInstance>::const_iterator it =
        instances.begin(); it != instances.end(); it++)
  {
    it->remove_space_fields(missing_fields);
    if (missing_fields.empty())
      break;
  }
  if (missing_fields.empty())
    return;
  // If we still have fields, we need to make an instance
  // We clearly need to take a guess, let's see if we can find
  // one of our instances to use.

  // ELLIOTT: Get the remote node here.
  Color index = runtime->get_logical_region_color(ctx, copy.src_requirements[idx].region);
  Memory target_memory = default_policy_select_target_memory(ctx,
                           procs_list[index % procs_list.size()]);
  log_stencil.warning("Building instance for copy of a region with index %u to be in memory %llx",
                      index, target_memory.id);
  bool force_new_instances = false;
  LayoutConstraintID our_layout_id =
   default_policy_select_layout_constraints(ctx, target_memory,
                                            req, COPY_MAPPING,
                                            true/*needs check*/,
                                            force_new_instances);
  LayoutConstraintSet creation_constraints =
              runtime->find_layout_constraints(ctx, our_layout_id);
  creation_constraints.add_constraint(
      FieldConstraint(missing_fields,
                      false/*contig*/, false/*inorder*/));
  instances.resize(instances.size() + 1);
  if (!default_make_instance(ctx, target_memory,
        creation_constraints, instances.back(),
        COPY_MAPPING, force_new_instances, true/*meets*/, req))
  {
    // If we failed to make it that is bad
    log_stencil.error("Stencil mapper failed allocation for "
                   "%s region requirement %d of explicit "
                   "region-to-region copy operation in task %s "
                   "(ID %lld) in memory " IDFMT " for processor "
                   IDFMT ". This means the working set of your "
                   "application is too big for the allotted "
                   "capacity of the given memory under the default "
                   "mapper's mapping scheme. You have three "
                   "choices: ask Realm to allocate more memory, "
                   "write a custom mapper to better manage working "
                   "sets, or find a bigger machine. Good luck!",
                   IS_SRC ? "source" : "destination", idx,
                   copy.parent_task->get_task_name(),
                   copy.parent_task->get_unique_id(),
		       target_memory.id,
		       copy.parent_task->current_proc.id);
    assert(false);
  }
}

static void create_mappers(Machine machine, HighLevelRuntime *runtime, const std::set<Processor> &local_procs)
{
  std::vector<Processor>* procs_list = new std::vector<Processor>();
  std::vector<Memory>* sysmems_list = new std::vector<Memory>();
  std::map<Memory, std::vector<Processor> >* sysmem_local_procs =
    new std::map<Memory, std::vector<Processor> >();
#if SPMD_SHARD_USE_IO_PROC
  std::map<Memory, std::vector<Processor> >* sysmem_local_io_procs =
    new std::map<Memory, std::vector<Processor> >();
#endif
  std::map<Processor, Memory>* proc_sysmems = new std::map<Processor, Memory>();
  std::map<Processor, Memory>* proc_regmems = new std::map<Processor, Memory>();

  std::vector<Machine::ProcessorMemoryAffinity> proc_mem_affinities;
  machine.get_proc_mem_affinity(proc_mem_affinities);

  for (unsigned idx = 0; idx < proc_mem_affinities.size(); ++idx) {
    Machine::ProcessorMemoryAffinity& affinity = proc_mem_affinities[idx];
    if (affinity.p.kind() == Processor::LOC_PROC) {
      if (affinity.m.kind() == Memory::SYSTEM_MEM) {
        (*proc_sysmems)[affinity.p] = affinity.m;
        if (proc_regmems->find(affinity.p) == proc_regmems->end())
          (*proc_regmems)[affinity.p] = affinity.m;
      }
      else if (affinity.m.kind() == Memory::REGDMA_MEM)
        (*proc_regmems)[affinity.p] = affinity.m;
    }
  }

  for (std::map<Processor, Memory>::iterator it = proc_sysmems->begin();
       it != proc_sysmems->end(); ++it) {
    if (it->first.kind() == Processor::LOC_PROC) {
      procs_list->push_back(it->first);
      (*sysmem_local_procs)[it->second].push_back(it->first);
    }
#if SPMD_SHARD_USE_IO_PROC
    else if (it->first.kind() == Processor::IO_PROC) {
      (*sysmem_local_io_procs)[it->second].push_back(it->first);
    }
#endif
  }

  for (std::map<Memory, std::vector<Processor> >::iterator it =
        sysmem_local_procs->begin(); it != sysmem_local_procs->end(); ++it)
    sysmems_list->push_back(it->first);

  for (std::set<Processor>::const_iterator it = local_procs.begin();
        it != local_procs.end(); it++)
  {
    StencilMapper* mapper = new StencilMapper(runtime->get_mapper_runtime(),
                                              machine, *it, "stencil_mapper",
                                              procs_list,
                                              sysmems_list,
                                              sysmem_local_procs,
#if SPMD_SHARD_USE_IO_PROC
                                              sysmem_local_io_procs,
#endif
                                              proc_sysmems,
                                              proc_regmems);
    runtime->replace_default_mapper(mapper, *it);
  }
}

void register_mappers()
{
  HighLevelRuntime::add_registration_callback(create_mappers);
}
<|endoftext|>