<commit_before>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2012 Scientific Computing and Imaging Institute,
   University of Utah.

   License for the specific language governing rights and limitations under
   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 <iostream>
#include <QtGui>
#include <Interface/Application/Port.h>
#include <Interface/Application/Connection.h>
#include <Interface/Application/PositionProvider.h>
#include <Interface/Application/Logger.h>
#include <Interface/Application/Utility.h>
#include <Interface/Application/ModuleProxyWidget.h>
#include <Interface/Application/ModuleWidget.h>

using namespace SCIRun::Gui;

QGraphicsScene* PortWidget::TheScene = 0;

PortWidget::PortWidget(const QString& name, const QColor& color, const QString& moduleId, size_t index,
  bool isInput, QWidget* parent /* = 0 */)
  : QWidget(parent),
  name_(name), color_(color), moduleId_(moduleId), index_(index), isInput_(isInput), isConnected_(false), lightOn_(false), currentConnection_(0),
  moduleParent_(parent)
{
  setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
  setAcceptDrops(true);
  setToolTip(name_);
}

QSize PortWidget::sizeHint() const
{
  const int width = 11;
  const int coloredHeight = isInput() ? 5 : 4;
  const int blackHeight = 2;
  return QSize(width, coloredHeight + blackHeight);
}

void PortWidget::toggleLight()
{
  lightOn_ = !lightOn_;
}

void PortWidget::turn_off_light()
{
  lightOn_ = false;
}

void PortWidget::turn_on_light()
{
  lightOn_ = true;
}

void PortWidget::paintEvent(QPaintEvent* event)
{
  QSize size = sizeHint();
  QPainter painter(this);
  painter.fillRect(QRect(QPoint(), size), color());
  QPoint lightStart = isInput() ? QPoint(0,5) : QPoint(0,0);
  QColor lightColor = isLightOn() ? Qt::red : Qt::black;
  painter.fillRect(QRect(lightStart, QSize(size.width(), 2)), lightColor);
}

void PortWidget::mousePressEvent(QMouseEvent* event)
{
  doMousePress(event->button(), event->pos());
}

void PortWidget::doMousePress(Qt::MouseButton button, const QPointF& pos)
{
  if (button == Qt::LeftButton && !isConnected())
  {
    toggleLight();
    startPos_ = pos;
    update();
  }
}

void PortWidget::mouseMoveEvent(QMouseEvent* event)
{
  doMouseMove(event->buttons(), event->pos());
}

void PortWidget::doMouseMove(Qt::MouseButtons buttons, const QPointF& pos)
{
  if (buttons & Qt::LeftButton)
  {
    int distance = (pos - startPos_).manhattanLength();
    if (distance >= QApplication::startDragDistance())
      performDrag(pos);
  }
}

void PortWidget::mouseReleaseEvent(QMouseEvent* event)
{
  doMouseRelease(event->button(), event->pos());
}

namespace
{
  const int PORT_CONNECTION_THRESHOLD = 12;
}

namespace SCIRun {
  namespace Gui {
    struct DeleteCurrentConnectionAtEndOfBlock
    {
      explicit DeleteCurrentConnectionAtEndOfBlock(PortWidget* p) : p_(p) {}
      ~DeleteCurrentConnectionAtEndOfBlock()
      {
        delete p_->currentConnection_;
        p_->currentConnection_ = 0;
      }
      PortWidget* p_;
    };
  }
}

void PortWidget::doMouseRelease(Qt::MouseButton button, const QPointF& pos)
{
  if (button == Qt::LeftButton && !isConnected())
  {
    toggleLight();
    update();

    if (currentConnection_)
    {
      makeConnection(pos);
    }
  }
}

void PortWidget::makeConnection(const QPointF& pos)
{
  DeleteCurrentConnectionAtEndOfBlock deleter(this);
  QList<QGraphicsItem*> items = TheScene->items(pos);
  Q_FOREACH (QGraphicsItem* item, items)
  {
    if (ModuleProxyWidget* mpw = dynamic_cast<ModuleProxyWidget*>(item))
    {
      ModuleWidget* overModule = mpw->getModule();
      if (overModule != moduleParent_)
      {
        const ModuleWidget::Ports& ports = isInput() ? overModule->getOutputPorts() : overModule->getInputPorts();
        Q_FOREACH (PortWidget* port, ports)
        {
          if (tryConnectPort(pos, port))
            return;
        }
      }
      else
      {
        std::cout << "trying to connect a module with itself, let's not allow circular connections yet." << std::endl;
      }
    }
  }
}

bool PortWidget::tryConnectPort(const QPointF& pos, PortWidget* port)
{
  int distance = (pos - port->position()).manhattanLength();
  if (distance <= PORT_CONNECTION_THRESHOLD)
  {
    if (canBeConnected(port))
    {
      Logger::Instance->log("Connection made.");

      SCIRun::Domain::Networks::ConnectionDescription cd(moduleId_.toStdString(), index_, port->moduleId_.toStdString(), port->index_);
      ConnectionLine* c = new ConnectionLine(this, port, SCIRun::Domain::Networks::ConnectionId::create(cd));
      TheScene->addItem(c);
      connect(c, SIGNAL(deleted(const SCIRun::Domain::Networks::ConnectionId&)), this, SIGNAL(connectionDeleted(const SCIRun::Domain::Networks::ConnectionId&)));
      Q_EMIT connectionMade(cd);

      return true;
    }
    else
    {
      std::cout << "input port is full, or ports are different datatype or same i/o type: should not be connected.  this message should come from the domain layer!" << std::endl;
    }
  }
  return false;
}

//TODO: push this verification down to the domain layer!  make this layer as dumb as possible
bool PortWidget::canBeConnected(PortWidget* other) const
{
  if (!other)
    return false;
  if (other->isInput() && !other->connections_.empty())
    return false;
  return color() == other->color() &&
    isInput() != other->isInput();
}

void PortWidget::performDrag(const QPointF& endPos)
{
  if (!currentConnection_)
  {
    //TODO: move into factory
    currentConnection_ = new ConnectionInProgress(this);
    if (TheScene)
      TheScene->addItem(currentConnection_);
    currentConnection_->setVisible(true);
  }
  currentConnection_->update(endPos);
}

void PortWidget::addConnection(ConnectionLine* c)
{
  connections_.insert(c);
}

void PortWidget::removeConnection(ConnectionLine* c)
{
  connections_.erase(c);
}

void PortWidget::deleteConnections()
{
  Q_FOREACH (ConnectionLine* c, connections_)
    delete c;
  connections_.clear();
}

void PortWidget::trackConnections()
{
  Q_FOREACH (ConnectionLine* c, connections_)
    c->trackNodes();
}

QPointF PortWidget::position() const
{
  if (positionProvider_)
    return positionProvider_->currentPosition();
  return pos();
}

InputPortWidget::InputPortWidget(const QString& name, const QColor& color, const QString& moduleId, size_t index, QWidget* parent /* = 0 */)
  : PortWidget(name, color, moduleId, index, true, parent)
{
}

OutputPortWidget::OutputPortWidget(const QString& name, const QColor& color, const QString& moduleId, size_t index, QWidget* parent /* = 0 */)
  : PortWidget(name, color, moduleId, index, false, parent)
{
}

<commit_msg>Fix bug with making connections.<commit_after>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2012 Scientific Computing and Imaging Institute,
   University of Utah.

   License for the specific language governing rights and limitations under
   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 <iostream>
#include <QtGui>
#include <Interface/Application/Port.h>
#include <Interface/Application/Connection.h>
#include <Interface/Application/PositionProvider.h>
#include <Interface/Application/Logger.h>
#include <Interface/Application/Utility.h>
#include <Interface/Application/ModuleProxyWidget.h>
#include <Interface/Application/ModuleWidget.h>

using namespace SCIRun::Gui;

QGraphicsScene* PortWidget::TheScene = 0;

PortWidget::PortWidget(const QString& name, const QColor& color, const QString& moduleId, size_t index,
  bool isInput, QWidget* parent /* = 0 */)
  : QWidget(parent),
  name_(name), color_(color), moduleId_(moduleId), index_(index), isInput_(isInput), isConnected_(false), lightOn_(false), currentConnection_(0),
  moduleParent_(parent)
{
  setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
  setAcceptDrops(true);
  setToolTip(name_);
}

QSize PortWidget::sizeHint() const
{
  const int width = 11;
  const int coloredHeight = isInput() ? 5 : 4;
  const int blackHeight = 2;
  return QSize(width, coloredHeight + blackHeight);
}

void PortWidget::toggleLight()
{
  lightOn_ = !lightOn_;
}

void PortWidget::turn_off_light()
{
  lightOn_ = false;
}

void PortWidget::turn_on_light()
{
  lightOn_ = true;
}

void PortWidget::paintEvent(QPaintEvent* event)
{
  QSize size = sizeHint();
  QPainter painter(this);
  painter.fillRect(QRect(QPoint(), size), color());
  QPoint lightStart = isInput() ? QPoint(0,5) : QPoint(0,0);
  QColor lightColor = isLightOn() ? Qt::red : Qt::black;
  painter.fillRect(QRect(lightStart, QSize(size.width(), 2)), lightColor);
}

void PortWidget::mousePressEvent(QMouseEvent* event)
{
  doMousePress(event->button(), event->pos());
}

void PortWidget::doMousePress(Qt::MouseButton button, const QPointF& pos)
{
  if (button == Qt::LeftButton && !isConnected())
  {
    toggleLight();
    startPos_ = pos;
    update();
  }
}

void PortWidget::mouseMoveEvent(QMouseEvent* event)
{
  doMouseMove(event->buttons(), event->pos());
}

void PortWidget::doMouseMove(Qt::MouseButtons buttons, const QPointF& pos)
{
  if (buttons & Qt::LeftButton)
  {
    int distance = (pos - startPos_).manhattanLength();
    if (distance >= QApplication::startDragDistance())
      performDrag(pos);
  }
}

void PortWidget::mouseReleaseEvent(QMouseEvent* event)
{
  doMouseRelease(event->button(), event->pos());
}

namespace
{
  const int PORT_CONNECTION_THRESHOLD = 12;
}

namespace SCIRun {
  namespace Gui {
    struct DeleteCurrentConnectionAtEndOfBlock
    {
      explicit DeleteCurrentConnectionAtEndOfBlock(PortWidget* p) : p_(p) {}
      ~DeleteCurrentConnectionAtEndOfBlock()
      {
        delete p_->currentConnection_;
        p_->currentConnection_ = 0;
      }
      PortWidget* p_;
    };
  }
}

void PortWidget::doMouseRelease(Qt::MouseButton button, const QPointF& pos)
{
  if (button == Qt::LeftButton && !isConnected())
  {
    toggleLight();
    update();

    if (currentConnection_)
    {
      makeConnection(pos);
    }
  }
}

void PortWidget::makeConnection(const QPointF& pos)
{
  DeleteCurrentConnectionAtEndOfBlock deleter(this);
  QList<QGraphicsItem*> items = TheScene->items(pos);
  Q_FOREACH (QGraphicsItem* item, items)
  {
    if (ModuleProxyWidget* mpw = dynamic_cast<ModuleProxyWidget*>(item))
    {
      ModuleWidget* overModule = mpw->getModule();
      if (overModule != moduleParent_)
      {
        const ModuleWidget::Ports& ports = isInput() ? overModule->getOutputPorts() : overModule->getInputPorts();
        Q_FOREACH (PortWidget* port, ports)
        {
          if (tryConnectPort(pos, port))
            return;
        }
      }
      else
      {
        std::cout << "trying to connect a module with itself, let's not allow circular connections yet." << std::endl;
      }
    }
  }
}

bool PortWidget::tryConnectPort(const QPointF& pos, PortWidget* port)
{
  int distance = (pos - port->position()).manhattanLength();
  if (distance <= PORT_CONNECTION_THRESHOLD)
  {
    if (canBeConnected(port))
    {
      Logger::Instance->log("Connection made.");

      PortWidget* start = isInput() ? port : this;
      PortWidget* end = isInput() ? this : port;

      SCIRun::Domain::Networks::ConnectionDescription cd(start->moduleId_.toStdString(), start->index_, end->moduleId_.toStdString(), end->index_);
      ConnectionLine* c = new ConnectionLine(this, port, SCIRun::Domain::Networks::ConnectionId::create(cd));
      TheScene->addItem(c);
      connect(c, SIGNAL(deleted(const SCIRun::Domain::Networks::ConnectionId&)), this, SIGNAL(connectionDeleted(const SCIRun::Domain::Networks::ConnectionId&)));
      Q_EMIT connectionMade(cd);

      return true;
    }
    else
    {
      std::cout << "input port is full, or ports are different datatype or same i/o type: should not be connected.  this message should come from the domain layer!" << std::endl;
    }
  }
  return false;
}

//TODO: push this verification down to the domain layer!  make this layer as dumb as possible
bool PortWidget::canBeConnected(PortWidget* other) const
{
  if (!other)
    return false;
  if (other->isInput() && !other->connections_.empty())
    return false;
  return color() == other->color() &&
    isInput() != other->isInput();
}

void PortWidget::performDrag(const QPointF& endPos)
{
  if (!currentConnection_)
  {
    //TODO: move into factory
    currentConnection_ = new ConnectionInProgress(this);
    if (TheScene)
      TheScene->addItem(currentConnection_);
    currentConnection_->setVisible(true);
  }
  currentConnection_->update(endPos);
}

void PortWidget::addConnection(ConnectionLine* c)
{
  connections_.insert(c);
}

void PortWidget::removeConnection(ConnectionLine* c)
{
  connections_.erase(c);
}

void PortWidget::deleteConnections()
{
  Q_FOREACH (ConnectionLine* c, connections_)
    delete c;
  connections_.clear();
}

void PortWidget::trackConnections()
{
  Q_FOREACH (ConnectionLine* c, connections_)
    c->trackNodes();
}

QPointF PortWidget::position() const
{
  if (positionProvider_)
    return positionProvider_->currentPosition();
  return pos();
}

InputPortWidget::InputPortWidget(const QString& name, const QColor& color, const QString& moduleId, size_t index, QWidget* parent /* = 0 */)
  : PortWidget(name, color, moduleId, index, true, parent)
{
}

OutputPortWidget::OutputPortWidget(const QString& name, const QColor& color, const QString& moduleId, size_t index, QWidget* parent /* = 0 */)
  : PortWidget(name, color, moduleId, index, false, parent)
{
}

<|endoftext|>


<commit_before>// Copyright (c) 2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <blockfilter.h>
#include <hash.h>
#include <primitives/transaction.h>
#include <script/script.h>
#include <streams.h>

/// SerType used to serialize parameters in GCS filter encoding.
static constexpr int GCS_SER_TYPE = SER_NETWORK;

/// Protocol version used to serialize parameters in GCS filter encoding.
static constexpr int GCS_SER_VERSION = 0;

template <typename OStream>
static void GolombRiceEncode(BitStreamWriter<OStream>& bitwriter, uint8_t P, uint64_t x)
{
    // Write quotient as unary-encoded: q 1's followed by one 0.
    uint64_t q = x >> P;
    while (q > 0) {
        int nbits = q <= 64 ? static_cast<int>(q) : 64;
        bitwriter.Write(~0ULL, nbits);
        q -= nbits;
    }
    bitwriter.Write(0, 1);

    // Write the remainder in P bits. Since the remainder is just the bottom
    // P bits of x, there is no need to mask first.
    bitwriter.Write(x, P);
}

template <typename IStream>
static uint64_t GolombRiceDecode(BitStreamReader<IStream>& bitreader, uint8_t P)
{
    // Read unary-encoded quotient: q 1's followed by one 0.
    uint64_t q = 0;
    while (bitreader.Read(1) == 1) {
        ++q;
    }

    uint64_t r = bitreader.Read(P);

    return (q << P) + r;
}

// Map a value x that is uniformly distributed in the range [0, 2^64) to a
// value uniformly distributed in [0, n) by returning the upper 64 bits of
// x * n.
//
// See: https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
static uint64_t MapIntoRange(uint64_t x, uint64_t n)
{
    // To perform the calculation on 64-bit numbers without losing the
    // result to overflow, split the numbers into the most significant and
    // least significant 32 bits and perform multiplication piece-wise.
    //
    // See: https://stackoverflow.com/a/26855440
    uint64_t x_hi = x >> 32;
    uint64_t x_lo = x & 0xFFFFFFFF;
    uint64_t n_hi = n >> 32;
    uint64_t n_lo = n & 0xFFFFFFFF;

    uint64_t ac = x_hi * n_hi;
    uint64_t ad = x_hi * n_lo;
    uint64_t bc = x_lo * n_hi;
    uint64_t bd = x_lo * n_lo;

    uint64_t mid34 = (bd >> 32) + (bc & 0xFFFFFFFF) + (ad & 0xFFFFFFFF);
    uint64_t upper64 = ac + (bc >> 32) + (ad >> 32) + (mid34 >> 32);
    return upper64;
}

uint64_t GCSFilter::HashToRange(const Element& element) const
{
    uint64_t hash = CSipHasher(m_siphash_k0, m_siphash_k1)
        .Write(element.data(), element.size())
        .Finalize();
    return MapIntoRange(hash, m_F);
}

std::vector<uint64_t> GCSFilter::BuildHashedSet(const ElementSet& elements) const
{
    std::vector<uint64_t> hashed_elements;
    hashed_elements.reserve(elements.size());
    for (const Element& element : elements) {
        hashed_elements.push_back(HashToRange(element));
    }
    std::sort(hashed_elements.begin(), hashed_elements.end());
    return hashed_elements;
}

GCSFilter::GCSFilter(uint64_t siphash_k0, uint64_t siphash_k1, uint8_t P, uint32_t M)
    : m_siphash_k0(siphash_k0), m_siphash_k1(siphash_k1), m_P(P), m_M(M), m_N(0), m_F(0)
{}

GCSFilter::GCSFilter(uint64_t siphash_k0, uint64_t siphash_k1, uint8_t P, uint32_t M,
                     std::vector<unsigned char> encoded_filter)
    : GCSFilter(siphash_k0, siphash_k1, P, M)
{
    m_encoded = std::move(encoded_filter);

    VectorReader stream(GCS_SER_TYPE, GCS_SER_VERSION, m_encoded, 0);

    uint64_t N = ReadCompactSize(stream);
    m_N = static_cast<uint32_t>(N);
    if (m_N != N) {
        throw std::ios_base::failure("N must be <2^32");
    }
    m_F = static_cast<uint64_t>(m_N) * static_cast<uint64_t>(m_M);

    // Verify that the encoded filter contains exactly N elements. If it has too much or too little
    // data, a std::ios_base::failure exception will be raised.
    BitStreamReader<VectorReader> bitreader(stream);
    for (uint64_t i = 0; i < m_N; ++i) {
        GolombRiceDecode(bitreader, m_P);
    }
    if (!stream.empty()) {
        throw std::ios_base::failure("encoded_filter contains excess data");
    }
}

GCSFilter::GCSFilter(uint64_t siphash_k0, uint64_t siphash_k1, uint8_t P, uint32_t M,
                     const ElementSet& elements)
    : GCSFilter(siphash_k0, siphash_k1, P, M)
{
    size_t N = elements.size();
    m_N = static_cast<uint32_t>(N);
    if (m_N != N) {
        throw std::invalid_argument("N must be <2^32");
    }
    m_F = static_cast<uint64_t>(m_N) * static_cast<uint64_t>(m_M);

    CVectorWriter stream(GCS_SER_TYPE, GCS_SER_VERSION, m_encoded, 0);

    WriteCompactSize(stream, m_N);

    if (elements.empty()) {
        return;
    }

    BitStreamWriter<CVectorWriter> bitwriter(stream);

    uint64_t last_value = 0;
    for (uint64_t value : BuildHashedSet(elements)) {
        uint64_t delta = value - last_value;
        GolombRiceEncode(bitwriter, m_P, delta);
        last_value = value;
    }

    bitwriter.Flush();
}

bool GCSFilter::MatchInternal(const uint64_t* element_hashes, size_t size) const
{
    VectorReader stream(GCS_SER_TYPE, GCS_SER_VERSION, m_encoded, 0);

    // Seek forward by size of N
    uint64_t N = ReadCompactSize(stream);
    assert(N == m_N);

    BitStreamReader<VectorReader> bitreader(stream);

    uint64_t value = 0;
    size_t hashes_index = 0;
    for (uint32_t i = 0; i < m_N; ++i) {
        uint64_t delta = GolombRiceDecode(bitreader, m_P);
        value += delta;

        while (true) {
            if (hashes_index == size) {
                return false;
            } else if (element_hashes[hashes_index] == value) {
                return true;
            } else if (element_hashes[hashes_index] > value) {
                break;
            }

            hashes_index++;
        }
    }

    return false;
}

bool GCSFilter::Match(const Element& element) const
{
    uint64_t query = HashToRange(element);
    return MatchInternal(&query, 1);
}

bool GCSFilter::MatchAny(const ElementSet& elements) const
{
    const std::vector<uint64_t> queries = BuildHashedSet(elements);
    return MatchInternal(queries.data(), queries.size());
}

static GCSFilter::ElementSet BasicFilterElements(const CBlock& block,
                                                 const CBlockUndo& block_undo)
{
    GCSFilter::ElementSet elements;

    for (const CTransactionRef& tx : block.vtx) {
        for (const CTxOut& txout : tx->vout) {
            const CScript& script = txout.scriptPubKey;
            if (script[0] == OP_RETURN) continue;
            elements.emplace(script.begin(), script.end());
        }
    }

    for (const CTxUndo& tx_undo : block_undo.vtxundo) {
        for (const Coin& prevout : tx_undo.vprevout) {
            const CScript& script = prevout.out.scriptPubKey;
            elements.emplace(script.begin(), script.end());
        }
    }

    return elements;
}

BlockFilter::BlockFilter(BlockFilterType filter_type, const CBlock& block, const CBlockUndo& block_undo)
    : m_filter_type(filter_type), m_block_hash(block.GetHash())
{
    switch (m_filter_type) {
    case BlockFilterType::BASIC:
        m_filter = GCSFilter(m_block_hash.GetUint64(0), m_block_hash.GetUint64(1),
                             BASIC_FILTER_P, BASIC_FILTER_M,
                             BasicFilterElements(block, block_undo));
        break;

    default:
        throw std::invalid_argument("unknown filter_type");
    }
}

uint256 BlockFilter::GetHash() const
{
    const std::vector<unsigned char>& data = GetEncodedFilter();

    uint256 result;
    CHash256().Write(data.data(), data.size()).Finalize(result.begin());
    return result;
}

uint256 BlockFilter::ComputeHeader(const uint256& prev_header) const
{
    const uint256& filter_hash = GetHash();

    uint256 result;
    CHash256()
        .Write(filter_hash.begin(), filter_hash.size())
        .Write(prev_header.begin(), prev_header.size())
        .Finalize(result.begin());
    return result;
}
<commit_msg>blockfilter: Optimization on compilers with int128 support.<commit_after>// Copyright (c) 2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <blockfilter.h>
#include <hash.h>
#include <primitives/transaction.h>
#include <script/script.h>
#include <streams.h>

/// SerType used to serialize parameters in GCS filter encoding.
static constexpr int GCS_SER_TYPE = SER_NETWORK;

/// Protocol version used to serialize parameters in GCS filter encoding.
static constexpr int GCS_SER_VERSION = 0;

template <typename OStream>
static void GolombRiceEncode(BitStreamWriter<OStream>& bitwriter, uint8_t P, uint64_t x)
{
    // Write quotient as unary-encoded: q 1's followed by one 0.
    uint64_t q = x >> P;
    while (q > 0) {
        int nbits = q <= 64 ? static_cast<int>(q) : 64;
        bitwriter.Write(~0ULL, nbits);
        q -= nbits;
    }
    bitwriter.Write(0, 1);

    // Write the remainder in P bits. Since the remainder is just the bottom
    // P bits of x, there is no need to mask first.
    bitwriter.Write(x, P);
}

template <typename IStream>
static uint64_t GolombRiceDecode(BitStreamReader<IStream>& bitreader, uint8_t P)
{
    // Read unary-encoded quotient: q 1's followed by one 0.
    uint64_t q = 0;
    while (bitreader.Read(1) == 1) {
        ++q;
    }

    uint64_t r = bitreader.Read(P);

    return (q << P) + r;
}

// Map a value x that is uniformly distributed in the range [0, 2^64) to a
// value uniformly distributed in [0, n) by returning the upper 64 bits of
// x * n.
//
// See: https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
static uint64_t MapIntoRange(uint64_t x, uint64_t n)
{
#ifdef __SIZEOF_INT128__
    return (static_cast<unsigned __int128>(x) * static_cast<unsigned __int128>(n)) >> 64;
#else
    // To perform the calculation on 64-bit numbers without losing the
    // result to overflow, split the numbers into the most significant and
    // least significant 32 bits and perform multiplication piece-wise.
    //
    // See: https://stackoverflow.com/a/26855440
    uint64_t x_hi = x >> 32;
    uint64_t x_lo = x & 0xFFFFFFFF;
    uint64_t n_hi = n >> 32;
    uint64_t n_lo = n & 0xFFFFFFFF;

    uint64_t ac = x_hi * n_hi;
    uint64_t ad = x_hi * n_lo;
    uint64_t bc = x_lo * n_hi;
    uint64_t bd = x_lo * n_lo;

    uint64_t mid34 = (bd >> 32) + (bc & 0xFFFFFFFF) + (ad & 0xFFFFFFFF);
    uint64_t upper64 = ac + (bc >> 32) + (ad >> 32) + (mid34 >> 32);
    return upper64;
#endif
}

uint64_t GCSFilter::HashToRange(const Element& element) const
{
    uint64_t hash = CSipHasher(m_siphash_k0, m_siphash_k1)
        .Write(element.data(), element.size())
        .Finalize();
    return MapIntoRange(hash, m_F);
}

std::vector<uint64_t> GCSFilter::BuildHashedSet(const ElementSet& elements) const
{
    std::vector<uint64_t> hashed_elements;
    hashed_elements.reserve(elements.size());
    for (const Element& element : elements) {
        hashed_elements.push_back(HashToRange(element));
    }
    std::sort(hashed_elements.begin(), hashed_elements.end());
    return hashed_elements;
}

GCSFilter::GCSFilter(uint64_t siphash_k0, uint64_t siphash_k1, uint8_t P, uint32_t M)
    : m_siphash_k0(siphash_k0), m_siphash_k1(siphash_k1), m_P(P), m_M(M), m_N(0), m_F(0)
{}

GCSFilter::GCSFilter(uint64_t siphash_k0, uint64_t siphash_k1, uint8_t P, uint32_t M,
                     std::vector<unsigned char> encoded_filter)
    : GCSFilter(siphash_k0, siphash_k1, P, M)
{
    m_encoded = std::move(encoded_filter);

    VectorReader stream(GCS_SER_TYPE, GCS_SER_VERSION, m_encoded, 0);

    uint64_t N = ReadCompactSize(stream);
    m_N = static_cast<uint32_t>(N);
    if (m_N != N) {
        throw std::ios_base::failure("N must be <2^32");
    }
    m_F = static_cast<uint64_t>(m_N) * static_cast<uint64_t>(m_M);

    // Verify that the encoded filter contains exactly N elements. If it has too much or too little
    // data, a std::ios_base::failure exception will be raised.
    BitStreamReader<VectorReader> bitreader(stream);
    for (uint64_t i = 0; i < m_N; ++i) {
        GolombRiceDecode(bitreader, m_P);
    }
    if (!stream.empty()) {
        throw std::ios_base::failure("encoded_filter contains excess data");
    }
}

GCSFilter::GCSFilter(uint64_t siphash_k0, uint64_t siphash_k1, uint8_t P, uint32_t M,
                     const ElementSet& elements)
    : GCSFilter(siphash_k0, siphash_k1, P, M)
{
    size_t N = elements.size();
    m_N = static_cast<uint32_t>(N);
    if (m_N != N) {
        throw std::invalid_argument("N must be <2^32");
    }
    m_F = static_cast<uint64_t>(m_N) * static_cast<uint64_t>(m_M);

    CVectorWriter stream(GCS_SER_TYPE, GCS_SER_VERSION, m_encoded, 0);

    WriteCompactSize(stream, m_N);

    if (elements.empty()) {
        return;
    }

    BitStreamWriter<CVectorWriter> bitwriter(stream);

    uint64_t last_value = 0;
    for (uint64_t value : BuildHashedSet(elements)) {
        uint64_t delta = value - last_value;
        GolombRiceEncode(bitwriter, m_P, delta);
        last_value = value;
    }

    bitwriter.Flush();
}

bool GCSFilter::MatchInternal(const uint64_t* element_hashes, size_t size) const
{
    VectorReader stream(GCS_SER_TYPE, GCS_SER_VERSION, m_encoded, 0);

    // Seek forward by size of N
    uint64_t N = ReadCompactSize(stream);
    assert(N == m_N);

    BitStreamReader<VectorReader> bitreader(stream);

    uint64_t value = 0;
    size_t hashes_index = 0;
    for (uint32_t i = 0; i < m_N; ++i) {
        uint64_t delta = GolombRiceDecode(bitreader, m_P);
        value += delta;

        while (true) {
            if (hashes_index == size) {
                return false;
            } else if (element_hashes[hashes_index] == value) {
                return true;
            } else if (element_hashes[hashes_index] > value) {
                break;
            }

            hashes_index++;
        }
    }

    return false;
}

bool GCSFilter::Match(const Element& element) const
{
    uint64_t query = HashToRange(element);
    return MatchInternal(&query, 1);
}

bool GCSFilter::MatchAny(const ElementSet& elements) const
{
    const std::vector<uint64_t> queries = BuildHashedSet(elements);
    return MatchInternal(queries.data(), queries.size());
}

static GCSFilter::ElementSet BasicFilterElements(const CBlock& block,
                                                 const CBlockUndo& block_undo)
{
    GCSFilter::ElementSet elements;

    for (const CTransactionRef& tx : block.vtx) {
        for (const CTxOut& txout : tx->vout) {
            const CScript& script = txout.scriptPubKey;
            if (script[0] == OP_RETURN) continue;
            elements.emplace(script.begin(), script.end());
        }
    }

    for (const CTxUndo& tx_undo : block_undo.vtxundo) {
        for (const Coin& prevout : tx_undo.vprevout) {
            const CScript& script = prevout.out.scriptPubKey;
            elements.emplace(script.begin(), script.end());
        }
    }

    return elements;
}

BlockFilter::BlockFilter(BlockFilterType filter_type, const CBlock& block, const CBlockUndo& block_undo)
    : m_filter_type(filter_type), m_block_hash(block.GetHash())
{
    switch (m_filter_type) {
    case BlockFilterType::BASIC:
        m_filter = GCSFilter(m_block_hash.GetUint64(0), m_block_hash.GetUint64(1),
                             BASIC_FILTER_P, BASIC_FILTER_M,
                             BasicFilterElements(block, block_undo));
        break;

    default:
        throw std::invalid_argument("unknown filter_type");
    }
}

uint256 BlockFilter::GetHash() const
{
    const std::vector<unsigned char>& data = GetEncodedFilter();

    uint256 result;
    CHash256().Write(data.data(), data.size()).Finalize(result.begin());
    return result;
}

uint256 BlockFilter::ComputeHeader(const uint256& prev_header) const
{
    const uint256& filter_hash = GetHash();

    uint256 result;
    CHash256()
        .Write(filter_hash.begin(), filter_hash.size())
        .Write(prev_header.begin(), prev_header.size())
        .Finalize(result.begin());
    return result;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: XMLShapeStyleContext.cxx,v $
 *
 *  $Revision: 1.14 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 18:08:55 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

#include <tools/debug.hxx>

#ifndef _XMLOFF_XMLSHAPESTYLECONTEXT_HXX
#include "XMLShapeStyleContext.hxx"
#endif
#ifndef _XMLOFF_XMLSHAPEPROPERTYSETCONTEXT_HXX
#include "XMLShapePropertySetContext.hxx"
#endif

#ifndef _XMLOFF_CONTEXTID_HXX_
#include "contextid.hxx"
#endif

#ifndef _COM_SUN_STAR_DRAWING_XCONTROLSHAPE_HPP_
#include <com/sun/star/drawing/XControlShape.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSETINFO_HPP_
#include "com/sun/star/beans/XPropertySetInfo.hpp"
#endif
#ifndef _COM_SUN_STAR_LANG_ILLEGALARGUMENTEXCEPTION_HPP_
#include <com/sun/star/lang/IllegalArgumentException.hpp>
#endif

#ifndef _XMLOFF_XMLIMP_HXX
#include "xmlimp.hxx"
#endif

#ifndef _XMLOFF_XMLNUMI_HXX
#include "xmlnumi.hxx"
#endif

#ifndef _XMLOFF_XMLNMSPE_HXX
#include <xmlnmspe.hxx>
#endif

#ifndef _XMLOFF_XMLTOKEN_HXX
#include "xmltoken.hxx"
#endif

#ifndef _XMLOFF_XMLERROR_HXX
#include "xmlerror.hxx"
#endif
#ifndef _XMLOFF_PROPMAPPINGTYPES_HXX
#include "maptype.hxx"
#endif

#include "sdpropls.hxx"

using namespace ::rtl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using ::xmloff::token::IsXMLToken;
using ::xmloff::token::XML_TEXT_PROPERTIES;
using ::xmloff::token::XML_GRAPHIC_PROPERTIES;
using ::xmloff::token::XML_PARAGRAPH_PROPERTIES;

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

TYPEINIT1( XMLShapeStyleContext, XMLPropStyleContext );

XMLShapeStyleContext::XMLShapeStyleContext(
    SvXMLImport& rImport,
    sal_uInt16 nPrfx,
    const OUString& rLName,
    const uno::Reference< xml::sax::XAttributeList >& xAttrList,
    SvXMLStylesContext& rStyles,
    sal_uInt16 nFamily)
:   XMLPropStyleContext(rImport, nPrfx, rLName, xAttrList, rStyles, nFamily ),
    m_bIsNumRuleAlreadyConverted( sal_False )
{
}

XMLShapeStyleContext::~XMLShapeStyleContext()
{
}

void XMLShapeStyleContext::SetAttribute( sal_uInt16 nPrefixKey, const ::rtl::OUString& rLocalName, const ::rtl::OUString& rValue )
{
    if ((0 == m_sControlDataStyleName.getLength()) && (::xmloff::token::GetXMLToken(::xmloff::token::XML_DATA_STYLE_NAME) == rLocalName))
    {
        m_sControlDataStyleName = rValue;
    }
    else if( (XML_NAMESPACE_STYLE == nPrefixKey) && IsXMLToken( rLocalName, ::xmloff::token::XML_LIST_STYLE_NAME ) )
    {
        m_sListStyleName = rValue;
    }
    else
    {
        XMLPropStyleContext::SetAttribute( nPrefixKey, rLocalName, rValue );

        if( (XML_NAMESPACE_STYLE == nPrefixKey) &&
            ( IsXMLToken( rLocalName, ::xmloff::token::XML_NAME ) || IsXMLToken( rLocalName, ::xmloff::token::XML_DISPLAY_NAME ) ) )
        {
            if( GetName().getLength() && GetDisplayName().getLength() && GetName() != GetDisplayName() )
            {
                const_cast< SvXMLImport&>( GetImport() ).
                    AddStyleDisplayName( GetFamily(), GetName(), GetDisplayName() );
            }
        }
    }
}

SvXMLImportContext *XMLShapeStyleContext::CreateChildContext(
        sal_uInt16 nPrefix,
        const OUString& rLocalName,
        const Reference< xml::sax::XAttributeList > & xAttrList )
{
    SvXMLImportContext *pContext = 0;

    if( XML_NAMESPACE_STYLE == nPrefix )
    {
        sal_uInt32 nFamily = 0;
        if( IsXMLToken( rLocalName, XML_TEXT_PROPERTIES ) )
            nFamily = XML_TYPE_PROP_TEXT;
        else if( IsXMLToken( rLocalName, XML_PARAGRAPH_PROPERTIES ) )
            nFamily = XML_TYPE_PROP_PARAGRAPH;
        else if( IsXMLToken( rLocalName, XML_GRAPHIC_PROPERTIES ) )
            nFamily = XML_TYPE_PROP_GRAPHIC;
        if( nFamily )
        {
            UniReference < SvXMLImportPropertyMapper > xImpPrMap =
                GetStyles()->GetImportPropertyMapper( GetFamily() );
            if( xImpPrMap.is() )
                pContext = new XMLShapePropertySetContext( GetImport(), nPrefix,
                                                        rLocalName, xAttrList,
                                                        nFamily,
                                                        GetProperties(),
                                                        xImpPrMap );
        }
    }

    if( !pContext )
        pContext = XMLPropStyleContext::CreateChildContext( nPrefix, rLocalName,
                                                          xAttrList );

    return pContext;
}

void XMLShapeStyleContext::FillPropertySet( const Reference< beans::XPropertySet > & rPropSet )
{
    if( !m_bIsNumRuleAlreadyConverted )
    {
        m_bIsNumRuleAlreadyConverted = sal_True;

        // for compatibility to beta files, search for CTF_SD_NUMBERINGRULES_NAME to
        // import numbering rules from the style:properties element
        const UniReference< XMLPropertySetMapper >&rMapper = GetStyles()->GetImportPropertyMapper( GetFamily() )->getPropertySetMapper();

        ::std::vector< XMLPropertyState > &rProperties = GetProperties();
        ::std::vector< XMLPropertyState >::iterator end( rProperties.end() );
        ::std::vector< XMLPropertyState >::iterator property;

        // first, look for the old format, where we had a text:list-style-name
        // attribute in the style:properties element
        for( property = rProperties.begin(); property != end; property++ )
        {
            // find properties with context
            if( (property->mnIndex != -1) && (rMapper->GetEntryContextId( property->mnIndex ) == CTF_SD_NUMBERINGRULES_NAME) )
                break;
        }

        // if we did not find an old list-style-name in the properties, and we need one
        // because we got a style:list-style attribute in the style-style element
        // we generate one
        if( (property == end) && ( 0 != m_sListStyleName.getLength() ) )
        {
            sal_Int32 nIndex = rMapper->FindEntryIndex( CTF_SD_NUMBERINGRULES_NAME );
            DBG_ASSERT( -1 != nIndex, "can't find numbering rules property entry, can't set numbering rule!" );

            XMLPropertyState aNewState( nIndex );
            rProperties.push_back( aNewState );
            end = rProperties.end();
            property = end - 1;
        }

        // so, if we have an old or a new list style name, we set its value to
        // a numbering rule
        if( property != end )
        {
            if( 0 == m_sListStyleName.getLength() )
            {
                property->maValue >>= m_sListStyleName;
            }

            const SvxXMLListStyleContext *pListStyle = GetImport().GetTextImport()->FindAutoListStyle( m_sListStyleName );

            DBG_ASSERT( pListStyle, "list-style not found for shape style" );
            if( pListStyle )
            {
                uno::Reference< container::XIndexReplace > xNumRule( pListStyle->CreateNumRule( GetImport().GetModel() ) );
                pListStyle->FillUnoNumRule(xNumRule, NULL /* const SvI18NMap * ??? */ );
                property->maValue <<= xNumRule;
            }
            else
            {
                property->mnIndex = -1;
            }
        }
    }

    const sal_uInt16 MAX_SPECIAL_DRAW_STYLES = 7;
    struct _ContextID_Index_Pair aContextIDs[MAX_SPECIAL_DRAW_STYLES+1] =
    {
        { CTF_DASHNAME , -1 },
        { CTF_LINESTARTNAME , -1 },
        { CTF_LINEENDNAME , -1 },
        { CTF_FILLGRADIENTNAME, -1 },
        { CTF_FILLTRANSNAME , -1 },
        { CTF_FILLHATCHNAME , -1 },
        { CTF_FILLBITMAPNAME , -1 },
        { -1, -1 }
    };
    static sal_uInt16 aFamilies[MAX_SPECIAL_DRAW_STYLES] =
    {
        XML_STYLE_FAMILY_SD_STROKE_DASH_ID,
        XML_STYLE_FAMILY_SD_MARKER_ID,
        XML_STYLE_FAMILY_SD_MARKER_ID,
        XML_STYLE_FAMILY_SD_GRADIENT_ID,
        XML_STYLE_FAMILY_SD_GRADIENT_ID,
        XML_STYLE_FAMILY_SD_HATCH_ID,
        XML_STYLE_FAMILY_SD_FILL_IMAGE_ID
    };

    UniReference < SvXMLImportPropertyMapper > xImpPrMap =
        GetStyles()->GetImportPropertyMapper( GetFamily() );
    DBG_ASSERT( xImpPrMap.is(), "There is the import prop mapper" );
    if( xImpPrMap.is() )
        xImpPrMap->FillPropertySet( GetProperties(), rPropSet, aContextIDs );

    Reference< XPropertySetInfo > xInfo;
    for( sal_uInt16 i=0; i<MAX_SPECIAL_DRAW_STYLES; i++ )
    {
        sal_Int32 nIndex = aContextIDs[i].nIndex;
        if( nIndex != -1 )
        {
            struct XMLPropertyState& rState = GetProperties()[nIndex];
            OUString sStyleName;
            rState.maValue >>= sStyleName;
            sStyleName = GetImport().GetStyleDisplayName( aFamilies[i],
                                                          sStyleName );
            // get property set mapper
            UniReference<XMLPropertySetMapper> rPropMapper =
                                        xImpPrMap->getPropertySetMapper();

            // set property
            const OUString& rPropertyName =
                    rPropMapper->GetEntryAPIName(rState.mnIndex);
            if( !xInfo.is() )
                xInfo = rPropSet->getPropertySetInfo();
            if ( xInfo->hasPropertyByName( rPropertyName ) )
            {
                Any aAny;
                aAny <<= sStyleName;

                try
                {
                    rPropSet->setPropertyValue( rPropertyName, aAny );
                }
                catch ( ::com::sun::star::lang::IllegalArgumentException& e )
                {
                    Sequence<OUString> aSeq(1);
                    aSeq[0] = sStyleName;
                    GetImport().SetError(
                        XMLERROR_STYLE_PROP_VALUE | XMLERROR_FLAG_ERROR,
                        aSeq, e.Message, NULL );
                }
            }
        }
    }

    if (m_sControlDataStyleName.getLength())
    {   // we had a data-style-name attribute

        // set the formatting on the control model of the control shape
        uno::Reference< drawing::XControlShape > xControlShape(rPropSet, uno::UNO_QUERY);
        DBG_ASSERT(xControlShape.is(), "XMLShapeStyleContext::FillPropertySet: data style for a non-control shape!");
        if (xControlShape.is())
        {
            uno::Reference< beans::XPropertySet > xControlModel(xControlShape->getControl(), uno::UNO_QUERY);
            DBG_ASSERT(xControlModel.is(), "XMLShapeStyleContext::FillPropertySet: no control model for the shape!");
            if (xControlModel.is())
            {
                GetImport().GetFormImport()->applyControlNumberStyle(xControlModel, m_sControlDataStyleName);
            }
        }
    }
}

void XMLShapeStyleContext::Finish( sal_Bool /*bOverwrite*/ )
{
}

<commit_msg>INTEGRATION: CWS pchfix02 (1.14.34); FILE MERGED 2006/09/01 17:59:32 kaib 1.14.34.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: XMLShapeStyleContext.cxx,v $
 *
 *  $Revision: 1.15 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 10:26:05 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"

#include <tools/debug.hxx>

#ifndef _XMLOFF_XMLSHAPESTYLECONTEXT_HXX
#include "XMLShapeStyleContext.hxx"
#endif
#ifndef _XMLOFF_XMLSHAPEPROPERTYSETCONTEXT_HXX
#include "XMLShapePropertySetContext.hxx"
#endif

#ifndef _XMLOFF_CONTEXTID_HXX_
#include "contextid.hxx"
#endif

#ifndef _COM_SUN_STAR_DRAWING_XCONTROLSHAPE_HPP_
#include <com/sun/star/drawing/XControlShape.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSETINFO_HPP_
#include "com/sun/star/beans/XPropertySetInfo.hpp"
#endif
#ifndef _COM_SUN_STAR_LANG_ILLEGALARGUMENTEXCEPTION_HPP_
#include <com/sun/star/lang/IllegalArgumentException.hpp>
#endif

#ifndef _XMLOFF_XMLIMP_HXX
#include "xmlimp.hxx"
#endif

#ifndef _XMLOFF_XMLNUMI_HXX
#include "xmlnumi.hxx"
#endif

#ifndef _XMLOFF_XMLNMSPE_HXX
#include <xmlnmspe.hxx>
#endif

#ifndef _XMLOFF_XMLTOKEN_HXX
#include "xmltoken.hxx"
#endif

#ifndef _XMLOFF_XMLERROR_HXX
#include "xmlerror.hxx"
#endif
#ifndef _XMLOFF_PROPMAPPINGTYPES_HXX
#include "maptype.hxx"
#endif

#include "sdpropls.hxx"

using namespace ::rtl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using ::xmloff::token::IsXMLToken;
using ::xmloff::token::XML_TEXT_PROPERTIES;
using ::xmloff::token::XML_GRAPHIC_PROPERTIES;
using ::xmloff::token::XML_PARAGRAPH_PROPERTIES;

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

TYPEINIT1( XMLShapeStyleContext, XMLPropStyleContext );

XMLShapeStyleContext::XMLShapeStyleContext(
    SvXMLImport& rImport,
    sal_uInt16 nPrfx,
    const OUString& rLName,
    const uno::Reference< xml::sax::XAttributeList >& xAttrList,
    SvXMLStylesContext& rStyles,
    sal_uInt16 nFamily)
:   XMLPropStyleContext(rImport, nPrfx, rLName, xAttrList, rStyles, nFamily ),
    m_bIsNumRuleAlreadyConverted( sal_False )
{
}

XMLShapeStyleContext::~XMLShapeStyleContext()
{
}

void XMLShapeStyleContext::SetAttribute( sal_uInt16 nPrefixKey, const ::rtl::OUString& rLocalName, const ::rtl::OUString& rValue )
{
    if ((0 == m_sControlDataStyleName.getLength()) && (::xmloff::token::GetXMLToken(::xmloff::token::XML_DATA_STYLE_NAME) == rLocalName))
    {
        m_sControlDataStyleName = rValue;
    }
    else if( (XML_NAMESPACE_STYLE == nPrefixKey) && IsXMLToken( rLocalName, ::xmloff::token::XML_LIST_STYLE_NAME ) )
    {
        m_sListStyleName = rValue;
    }
    else
    {
        XMLPropStyleContext::SetAttribute( nPrefixKey, rLocalName, rValue );

        if( (XML_NAMESPACE_STYLE == nPrefixKey) &&
            ( IsXMLToken( rLocalName, ::xmloff::token::XML_NAME ) || IsXMLToken( rLocalName, ::xmloff::token::XML_DISPLAY_NAME ) ) )
        {
            if( GetName().getLength() && GetDisplayName().getLength() && GetName() != GetDisplayName() )
            {
                const_cast< SvXMLImport&>( GetImport() ).
                    AddStyleDisplayName( GetFamily(), GetName(), GetDisplayName() );
            }
        }
    }
}

SvXMLImportContext *XMLShapeStyleContext::CreateChildContext(
        sal_uInt16 nPrefix,
        const OUString& rLocalName,
        const Reference< xml::sax::XAttributeList > & xAttrList )
{
    SvXMLImportContext *pContext = 0;

    if( XML_NAMESPACE_STYLE == nPrefix )
    {
        sal_uInt32 nFamily = 0;
        if( IsXMLToken( rLocalName, XML_TEXT_PROPERTIES ) )
            nFamily = XML_TYPE_PROP_TEXT;
        else if( IsXMLToken( rLocalName, XML_PARAGRAPH_PROPERTIES ) )
            nFamily = XML_TYPE_PROP_PARAGRAPH;
        else if( IsXMLToken( rLocalName, XML_GRAPHIC_PROPERTIES ) )
            nFamily = XML_TYPE_PROP_GRAPHIC;
        if( nFamily )
        {
            UniReference < SvXMLImportPropertyMapper > xImpPrMap =
                GetStyles()->GetImportPropertyMapper( GetFamily() );
            if( xImpPrMap.is() )
                pContext = new XMLShapePropertySetContext( GetImport(), nPrefix,
                                                        rLocalName, xAttrList,
                                                        nFamily,
                                                        GetProperties(),
                                                        xImpPrMap );
        }
    }

    if( !pContext )
        pContext = XMLPropStyleContext::CreateChildContext( nPrefix, rLocalName,
                                                          xAttrList );

    return pContext;
}

void XMLShapeStyleContext::FillPropertySet( const Reference< beans::XPropertySet > & rPropSet )
{
    if( !m_bIsNumRuleAlreadyConverted )
    {
        m_bIsNumRuleAlreadyConverted = sal_True;

        // for compatibility to beta files, search for CTF_SD_NUMBERINGRULES_NAME to
        // import numbering rules from the style:properties element
        const UniReference< XMLPropertySetMapper >&rMapper = GetStyles()->GetImportPropertyMapper( GetFamily() )->getPropertySetMapper();

        ::std::vector< XMLPropertyState > &rProperties = GetProperties();
        ::std::vector< XMLPropertyState >::iterator end( rProperties.end() );
        ::std::vector< XMLPropertyState >::iterator property;

        // first, look for the old format, where we had a text:list-style-name
        // attribute in the style:properties element
        for( property = rProperties.begin(); property != end; property++ )
        {
            // find properties with context
            if( (property->mnIndex != -1) && (rMapper->GetEntryContextId( property->mnIndex ) == CTF_SD_NUMBERINGRULES_NAME) )
                break;
        }

        // if we did not find an old list-style-name in the properties, and we need one
        // because we got a style:list-style attribute in the style-style element
        // we generate one
        if( (property == end) && ( 0 != m_sListStyleName.getLength() ) )
        {
            sal_Int32 nIndex = rMapper->FindEntryIndex( CTF_SD_NUMBERINGRULES_NAME );
            DBG_ASSERT( -1 != nIndex, "can't find numbering rules property entry, can't set numbering rule!" );

            XMLPropertyState aNewState( nIndex );
            rProperties.push_back( aNewState );
            end = rProperties.end();
            property = end - 1;
        }

        // so, if we have an old or a new list style name, we set its value to
        // a numbering rule
        if( property != end )
        {
            if( 0 == m_sListStyleName.getLength() )
            {
                property->maValue >>= m_sListStyleName;
            }

            const SvxXMLListStyleContext *pListStyle = GetImport().GetTextImport()->FindAutoListStyle( m_sListStyleName );

            DBG_ASSERT( pListStyle, "list-style not found for shape style" );
            if( pListStyle )
            {
                uno::Reference< container::XIndexReplace > xNumRule( pListStyle->CreateNumRule( GetImport().GetModel() ) );
                pListStyle->FillUnoNumRule(xNumRule, NULL /* const SvI18NMap * ??? */ );
                property->maValue <<= xNumRule;
            }
            else
            {
                property->mnIndex = -1;
            }
        }
    }

    const sal_uInt16 MAX_SPECIAL_DRAW_STYLES = 7;
    struct _ContextID_Index_Pair aContextIDs[MAX_SPECIAL_DRAW_STYLES+1] =
    {
        { CTF_DASHNAME , -1 },
        { CTF_LINESTARTNAME , -1 },
        { CTF_LINEENDNAME , -1 },
        { CTF_FILLGRADIENTNAME, -1 },
        { CTF_FILLTRANSNAME , -1 },
        { CTF_FILLHATCHNAME , -1 },
        { CTF_FILLBITMAPNAME , -1 },
        { -1, -1 }
    };
    static sal_uInt16 aFamilies[MAX_SPECIAL_DRAW_STYLES] =
    {
        XML_STYLE_FAMILY_SD_STROKE_DASH_ID,
        XML_STYLE_FAMILY_SD_MARKER_ID,
        XML_STYLE_FAMILY_SD_MARKER_ID,
        XML_STYLE_FAMILY_SD_GRADIENT_ID,
        XML_STYLE_FAMILY_SD_GRADIENT_ID,
        XML_STYLE_FAMILY_SD_HATCH_ID,
        XML_STYLE_FAMILY_SD_FILL_IMAGE_ID
    };

    UniReference < SvXMLImportPropertyMapper > xImpPrMap =
        GetStyles()->GetImportPropertyMapper( GetFamily() );
    DBG_ASSERT( xImpPrMap.is(), "There is the import prop mapper" );
    if( xImpPrMap.is() )
        xImpPrMap->FillPropertySet( GetProperties(), rPropSet, aContextIDs );

    Reference< XPropertySetInfo > xInfo;
    for( sal_uInt16 i=0; i<MAX_SPECIAL_DRAW_STYLES; i++ )
    {
        sal_Int32 nIndex = aContextIDs[i].nIndex;
        if( nIndex != -1 )
        {
            struct XMLPropertyState& rState = GetProperties()[nIndex];
            OUString sStyleName;
            rState.maValue >>= sStyleName;
            sStyleName = GetImport().GetStyleDisplayName( aFamilies[i],
                                                          sStyleName );
            // get property set mapper
            UniReference<XMLPropertySetMapper> rPropMapper =
                                        xImpPrMap->getPropertySetMapper();

            // set property
            const OUString& rPropertyName =
                    rPropMapper->GetEntryAPIName(rState.mnIndex);
            if( !xInfo.is() )
                xInfo = rPropSet->getPropertySetInfo();
            if ( xInfo->hasPropertyByName( rPropertyName ) )
            {
                Any aAny;
                aAny <<= sStyleName;

                try
                {
                    rPropSet->setPropertyValue( rPropertyName, aAny );
                }
                catch ( ::com::sun::star::lang::IllegalArgumentException& e )
                {
                    Sequence<OUString> aSeq(1);
                    aSeq[0] = sStyleName;
                    GetImport().SetError(
                        XMLERROR_STYLE_PROP_VALUE | XMLERROR_FLAG_ERROR,
                        aSeq, e.Message, NULL );
                }
            }
        }
    }

    if (m_sControlDataStyleName.getLength())
    {   // we had a data-style-name attribute

        // set the formatting on the control model of the control shape
        uno::Reference< drawing::XControlShape > xControlShape(rPropSet, uno::UNO_QUERY);
        DBG_ASSERT(xControlShape.is(), "XMLShapeStyleContext::FillPropertySet: data style for a non-control shape!");
        if (xControlShape.is())
        {
            uno::Reference< beans::XPropertySet > xControlModel(xControlShape->getControl(), uno::UNO_QUERY);
            DBG_ASSERT(xControlModel.is(), "XMLShapeStyleContext::FillPropertySet: no control model for the shape!");
            if (xControlModel.is())
            {
                GetImport().GetFormImport()->applyControlNumberStyle(xControlModel, m_sControlDataStyleName);
            }
        }
    }
}

void XMLShapeStyleContext::Finish( sal_Bool /*bOverwrite*/ )
{
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: MutableAttrList.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2004-07-13 08:53:49 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _XMLOFF_MUTABLEATTRLIST_HXX
#define _XMLOFF_MUTABLEATTRLIST_HXX

#ifndef _COM_SUN_STAR_UTIL_XCLONEABLE_HPP_
#include <com/sun/star/util/XCloneable.hpp>
#endif
#ifndef _COM_SUN_STAR_XML_SAX_XATTRIBUTELIST_HPP_
#include <com/sun/star/xml/sax/XAttributeList.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEL_HPP_
#include <com/sun/star/lang/XUnoTunnel.hpp>
#endif

#include <cppuhelper/implbase3.hxx>

class SvXMLAttributeList;

class XMLMutableAttributeList : public ::cppu::WeakImplHelper3<
        ::com::sun::star::xml::sax::XAttributeList,
        ::com::sun::star::util::XCloneable,
        ::com::sun::star::lang::XUnoTunnel>
{
    ::com::sun::star::uno::Reference<
        ::com::sun::star::xml::sax::XAttributeList> m_xAttrList;

    SvXMLAttributeList *m_pMutableAttrList;

    SvXMLAttributeList *GetMutableAttrList();

public:
    XMLMutableAttributeList();
    XMLMutableAttributeList( const ::com::sun::star::uno::Reference<
        ::com::sun::star::xml::sax::XAttributeList> & rAttrList,
           sal_Bool bClone=sal_False );
    ~XMLMutableAttributeList();

    static const ::com::sun::star::uno::Sequence< sal_Int8 > & getUnoTunnelId() throw();
    static XMLMutableAttributeList* getImplementation( ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > ) throw();

    // XUnoTunnel
    virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException);

    // ::com::sun::star::xml::sax::XAttributeList
    virtual sal_Int16 SAL_CALL getLength(void) throw( ::com::sun::star::uno::RuntimeException );
    virtual ::rtl::OUString SAL_CALL getNameByIndex(sal_Int16 i) throw( ::com::sun::star::uno::RuntimeException );
    virtual ::rtl::OUString SAL_CALL getTypeByIndex(sal_Int16 i) throw( ::com::sun::star::uno::RuntimeException );
    virtual ::rtl::OUString SAL_CALL getTypeByName(const ::rtl::OUString& aName) throw( ::com::sun::star::uno::RuntimeException );
    virtual ::rtl::OUString SAL_CALL getValueByIndex(sal_Int16 i) throw( ::com::sun::star::uno::RuntimeException );
    virtual ::rtl::OUString SAL_CALL getValueByName(const ::rtl::OUString& aName) throw( ::com::sun::star::uno::RuntimeException );

    // ::com::sun::star::util::XCloneable
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloneable > SAL_CALL createClone()   throw( ::com::sun::star::uno::RuntimeException );

    // methods that are not contained in any interface
    void SetValueByIndex( sal_Int16 i, const ::rtl::OUString& rValue );
    void AddAttribute( const ::rtl::OUString &sName , const ::rtl::OUString &sValue );
//  void Clear();
    void RemoveAttributeByIndex( sal_Int16 i );
    void RenameAttributeByIndex( sal_Int16 i, const ::rtl::OUString& rNewName );
//  void SetAttributeList( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > & );
    void AppendAttributeList( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > & );

    sal_Int16 GetIndexByName( const ::rtl::OUString& rName ) const;
};

#endif  //  _XMLOFF_MUTABLEATTRLIST_HXX
<commit_msg>INTEGRATION: CWS ooo19126 (1.2.300); FILE MERGED 2005/09/05 14:40:25 rt 1.2.300.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: MutableAttrList.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 15:48:49 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

#ifndef _XMLOFF_MUTABLEATTRLIST_HXX
#define _XMLOFF_MUTABLEATTRLIST_HXX

#ifndef _COM_SUN_STAR_UTIL_XCLONEABLE_HPP_
#include <com/sun/star/util/XCloneable.hpp>
#endif
#ifndef _COM_SUN_STAR_XML_SAX_XATTRIBUTELIST_HPP_
#include <com/sun/star/xml/sax/XAttributeList.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEL_HPP_
#include <com/sun/star/lang/XUnoTunnel.hpp>
#endif

#include <cppuhelper/implbase3.hxx>

class SvXMLAttributeList;

class XMLMutableAttributeList : public ::cppu::WeakImplHelper3<
        ::com::sun::star::xml::sax::XAttributeList,
        ::com::sun::star::util::XCloneable,
        ::com::sun::star::lang::XUnoTunnel>
{
    ::com::sun::star::uno::Reference<
        ::com::sun::star::xml::sax::XAttributeList> m_xAttrList;

    SvXMLAttributeList *m_pMutableAttrList;

    SvXMLAttributeList *GetMutableAttrList();

public:
    XMLMutableAttributeList();
    XMLMutableAttributeList( const ::com::sun::star::uno::Reference<
        ::com::sun::star::xml::sax::XAttributeList> & rAttrList,
           sal_Bool bClone=sal_False );
    ~XMLMutableAttributeList();

    static const ::com::sun::star::uno::Sequence< sal_Int8 > & getUnoTunnelId() throw();
    static XMLMutableAttributeList* getImplementation( ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > ) throw();

    // XUnoTunnel
    virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException);

    // ::com::sun::star::xml::sax::XAttributeList
    virtual sal_Int16 SAL_CALL getLength(void) throw( ::com::sun::star::uno::RuntimeException );
    virtual ::rtl::OUString SAL_CALL getNameByIndex(sal_Int16 i) throw( ::com::sun::star::uno::RuntimeException );
    virtual ::rtl::OUString SAL_CALL getTypeByIndex(sal_Int16 i) throw( ::com::sun::star::uno::RuntimeException );
    virtual ::rtl::OUString SAL_CALL getTypeByName(const ::rtl::OUString& aName) throw( ::com::sun::star::uno::RuntimeException );
    virtual ::rtl::OUString SAL_CALL getValueByIndex(sal_Int16 i) throw( ::com::sun::star::uno::RuntimeException );
    virtual ::rtl::OUString SAL_CALL getValueByName(const ::rtl::OUString& aName) throw( ::com::sun::star::uno::RuntimeException );

    // ::com::sun::star::util::XCloneable
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloneable > SAL_CALL createClone()   throw( ::com::sun::star::uno::RuntimeException );

    // methods that are not contained in any interface
    void SetValueByIndex( sal_Int16 i, const ::rtl::OUString& rValue );
    void AddAttribute( const ::rtl::OUString &sName , const ::rtl::OUString &sValue );
//  void Clear();
    void RemoveAttributeByIndex( sal_Int16 i );
    void RenameAttributeByIndex( sal_Int16 i, const ::rtl::OUString& rNewName );
//  void SetAttributeList( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > & );
    void AppendAttributeList( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > & );

    sal_Int16 GetIndexByName( const ::rtl::OUString& rName ) const;
};

#endif  //  _XMLOFF_MUTABLEATTRLIST_HXX
<|endoftext|>


<commit_before>#include <algorithm>
#include <iostream>
#include <mutex>
#include <string>
#include <stdint.h>
#include <tuple>
#include <vector>
#include <unordered_map>

typedef struct CUfunc_st *CUfunction;
typedef struct CUmod_st *CUmodule;
typedef struct CUstream_st *CUstream;
typedef int CUdevice;

//include the cuda function prototypes here so that we don't need to know
//anything about cuda to compile this file - makes building with bazel
//a million times easier
extern "C" {

int
#ifdef _WIN32
__stdcall
#endif
cuModuleLoadData(CUmodule *, const void *);

int
#ifdef _WIN32
__stdcall
#endif
cuModuleGetFunction(CUfunction *, CUmodule, const char *);

int
#ifdef _WIN32
__stdcall
#endif
cuDeviceGetAttribute(int *, int, CUdevice);

int
#ifdef _WIN32
__stdcall
#endif
cuLaunchKernel(CUfunction,
               unsigned int,
               unsigned int,
               unsigned int,
               unsigned int,
               unsigned int,
               unsigned int,
               unsigned int,
               CUstream,
               void **,
               void **);

int
#ifdef _WIN32
__stdcall
#endif
cuCtxGetDevice(CUdevice *);

};

#include "include/c_interface.h"
#include "include/kernel_headers.h"

namespace {
#include "include/static_kernel_information.h"

std::mutex load_kernel_mutex_;

std::unordered_map<std::string, CUfunction> kernels_;

bool loadKernelsHelper(const std::unordered_map<std::string, const uint8_t*>& kernels) {
  for (auto kernel : kernels) {
    if (kernels_.count(kernel.first) > 0)
      continue;

    CUmodule module;

    int res = cuModuleLoadData(&module, kernel.second);
    if (res != 0) {
      std::cerr << "Failed to load " << kernel.first << " " <<
                res << std::endl;
      return false;
    }

    CUfunction function;

    std::string kernel_name = kernel.first.substr(0, kernel.first.size() - 6);

    res = cuModuleGetFunction(&function, module, kernel_name.c_str());
    if (res != 0) {
      std::cerr << "Failed to extract " << kernel_name << " " <<
                res << std::endl;
      return false;
    }

    kernels_.insert(std::make_pair(kernel.first, function));
  }

  return true;
}

bool loadKernels(int major) {
  std::lock_guard<std::mutex> lock(load_kernel_mutex_);

  if (major == 5)
    return loadKernelsHelper(kernels_50);
  else if (major == 6)
    return loadKernelsHelper(kernels_60);
  else {
    std::cerr << "Arch must be 5 or 6" << std::endl;
    return false;
  }
}

std::tuple<int, int, int> getDeviceProperties(CUdevice& device) {
  int major, minor;
  int res = cuDeviceGetAttribute(&major, 75, device);
  if (res != 0)
    return std::make_tuple(res, -1, -1);

  res = cuDeviceGetAttribute(&minor, 76, device);
  if (res != 0)
    return std::make_tuple(res, -1, -1);

  return std::make_tuple(0, major, minor);
}

std::pair<int, int> closest_divisor(int val, int div) {
  if (div == 2) {
    if ((val & 1) == 0) { return std::make_pair(2, val >> 1);  }
    else                { return std::make_pair(1, val);       }
  }
  else if (div == 4) {
    if      ((val & 3) == 0) { return std::make_pair(4, val >> 2); }
    else if ((val % 3) == 0) { return std::make_pair(3, val / 3);  }
    else if ((val % 5) == 0) { return std::make_pair(5, val / 5);  }
    else if ((val & 1) == 0) { return std::make_pair(2, val >> 1); }
    else if ((val % 7) == 0) { return std::make_pair(7, val / 7);  }
    else                     { return std::make_pair(1, val);      }
  }
}

std::string get_op_string(bool a_t, bool b_t) {
  if      (!a_t && !b_t) return "NN";
  else if (a_t && !b_t)  return "TN";
  else if (!a_t && b_t)  return "NT";
  else                   return "TT";
}

bool gemm(std::string precision, void *A, void *B, void *C,
          bool a_t, bool b_t,
          int m, int n, int k,
          int lda, int ldb, int ldc,
          float alpha, float beta,
          CUstream stream, unsigned int grid, unsigned int shared) {
  std::string kernel_op = get_op_string(a_t, b_t);

  if (grid >= selections[precision][kernel_op].size())
    return false;

  kernel_properties kp = selections[precision][kernel_op][grid];

  if (shared >= kp.shared_sizes.size())
    return false;

  bool vec4A, vec8A;
  bool vec4B, vec8B;
  if (a_t) {
    vec4A = (lda & 3) == 0 && (m & 3) == 0; //multiple of 4
    vec8A = (lda & 7) == 0 && (m & 7) == 0; //multiple of 8
  }
  else {
    vec4A = (lda & 3) == 0 && (k & 3) == 0; //multiple of 4
    vec8A = (lda & 7) == 0 && (k & 7) == 0; //multiple of 8
  }

  if (b_t) {
    vec4B = (ldb & 3) == 0 && (k & 3) == 0; //multiple of 4
    vec8B = (ldb & 7) == 0 && (k & 7) == 0; //multiple of 8
  }
  else {
    vec4B = (ldb & 3) == 0 && (n & 3) == 0; //multiple of 4
    vec8B = (ldb & 7) == 0 && (n & 7) == 0; //multiple of 8
  }

  bool vec4C = (ldc & 3) == 0 && (n & 3) == 0;

  bool vecA = (kp.vA == 4 && vec4A) || (kp.vA == 8 && vec8A);
  bool vecB = (kp.vB == 4 && vec4B) || (kp.vB == 8 && vec8B);
  bool vecC = kp.vC == 1 || vec4C;

  bool vec = vecA && vecB && vecC;

  CUdevice device;
  int res = cuCtxGetDevice(&device);
  if (res != 0)
    return false;

  bool success;
  int major, minor;

  std::tie(success, major, minor) = getDeviceProperties(device);

  if (success != 0)
    return false;

  std::string kernel_string;
  kernel_string.reserve(64);

  kernel_string += precision + "gemm_" + kp.tile_string +
                   "_" + kernel_op;
  if (vec)
    kernel_string += "_vec";

  if (major == 5)
    kernel_string += "_sm_50";
  else if (major == 6)
    kernel_string += "_sm_60";
  else
    return false;

  auto kernel = kernels_.find(kernel_string);
  if (kernel == kernels_.end()) {
    loadKernels(major);
    kernel = kernels_.find(kernel_string);
  }

  int blk_A = (m + kp.tile_m - 1) / kp.tile_m;
  int blk_B = (n + kp.tile_n - 1) / kp.tile_n;

  int blk_a, blk_b;
  std::tie(blk_a, blk_A) = closest_divisor(blk_A, kp.div);
  std::tie(blk_b, blk_B) = closest_divisor(blk_B, kp.div);

  if (blk_a == 1)
    std::tie(blk_a, blk_A) = std::make_pair(blk_A, 1);

  void *args[13] = {&C, &A, &B, &alpha, &beta, &lda, &ldb, &ldc,
                    &m, &n, &k, &blk_a, &blk_b};

  res = cuLaunchKernel(kernel->second, blk_a * blk_b, blk_B, blk_A,
                       kp.threads, 1, 1,
                       kp.shared_sizes[shared], stream, args, NULL);

  if (res != 0) {
    std::cerr << "Failed to execute " << kernel_string << " " <<
      res << std::endl;
    return false;
  }

  return true;
}

};

bool get_grid_limits(char precision, bool a_t, bool b_t, unsigned int *grid)
{
  std::string prec_string(1, precision);

  *grid = selections[prec_string][get_op_string(a_t, b_t)].size();
  return true;
}

bool get_shared_limits(char precision, bool a_t, bool b_t, unsigned int grid, unsigned int *shared) {
  std::string prec_string(1, precision);

  if (grid >= selections[prec_string][get_op_string(a_t, b_t)].size())
    return false;

  *shared = selections[prec_string][get_op_string(a_t, b_t)][grid].shared_sizes.size();

  return true;
}

bool openai_sgemm(float *A, float *B, float *C,
           bool a_t, bool b_t,
           int m, int n, int k,
           int lda, int ldb, int ldc,
           float alpha, float beta,
           CUstream stream, unsigned int grid, unsigned int shared) {
  return gemm("s",
              static_cast<void*>(A),
              static_cast<void*>(B),
              static_cast<void*>(C),
              a_t, b_t, m, n, k, lda, ldb, ldc,
              alpha, beta, stream, grid, shared);
}

bool openai_hgemm(uint16_t *A, uint16_t *B, uint16_t *C,
           bool a_t, bool b_t,
           int m, int n, int k,
           int lda, int ldb, int ldc,
           float alpha, float beta,
           CUstream stream, unsigned int grid, unsigned int shared) {
  return gemm("h",
              static_cast<void*>(A),
              static_cast<void*>(B),
              static_cast<void*>(C),
              a_t, b_t, m, n, k, lda, ldb, ldc,
              alpha, beta, stream, grid, shared);
}
<commit_msg>remove unused header<commit_after>#include <iostream>
#include <mutex>
#include <string>
#include <stdint.h>
#include <tuple>
#include <vector>
#include <unordered_map>

typedef struct CUfunc_st *CUfunction;
typedef struct CUmod_st *CUmodule;
typedef struct CUstream_st *CUstream;
typedef int CUdevice;

//include the cuda function prototypes here so that we don't need to know
//anything about cuda to compile this file - makes building with bazel
//a million times easier
extern "C" {

int
#ifdef _WIN32
__stdcall
#endif
cuModuleLoadData(CUmodule *, const void *);

int
#ifdef _WIN32
__stdcall
#endif
cuModuleGetFunction(CUfunction *, CUmodule, const char *);

int
#ifdef _WIN32
__stdcall
#endif
cuDeviceGetAttribute(int *, int, CUdevice);

int
#ifdef _WIN32
__stdcall
#endif
cuLaunchKernel(CUfunction,
               unsigned int,
               unsigned int,
               unsigned int,
               unsigned int,
               unsigned int,
               unsigned int,
               unsigned int,
               CUstream,
               void **,
               void **);

int
#ifdef _WIN32
__stdcall
#endif
cuCtxGetDevice(CUdevice *);

};

#include "include/c_interface.h"
#include "include/kernel_headers.h"

namespace {
#include "include/static_kernel_information.h"

std::mutex load_kernel_mutex_;

std::unordered_map<std::string, CUfunction> kernels_;

bool loadKernelsHelper(const std::unordered_map<std::string, const uint8_t*>& kernels) {
  for (auto kernel : kernels) {
    if (kernels_.count(kernel.first) > 0)
      continue;

    CUmodule module;

    int res = cuModuleLoadData(&module, kernel.second);
    if (res != 0) {
      std::cerr << "Failed to load " << kernel.first << " " <<
                res << std::endl;
      return false;
    }

    CUfunction function;

    std::string kernel_name = kernel.first.substr(0, kernel.first.size() - 6);

    res = cuModuleGetFunction(&function, module, kernel_name.c_str());
    if (res != 0) {
      std::cerr << "Failed to extract " << kernel_name << " " <<
                res << std::endl;
      return false;
    }

    kernels_.insert(std::make_pair(kernel.first, function));
  }

  return true;
}

bool loadKernels(int major) {
  std::lock_guard<std::mutex> lock(load_kernel_mutex_);

  if (major == 5)
    return loadKernelsHelper(kernels_50);
  else if (major == 6)
    return loadKernelsHelper(kernels_60);
  else {
    std::cerr << "Arch must be 5 or 6" << std::endl;
    return false;
  }
}

std::tuple<int, int, int> getDeviceProperties(CUdevice& device) {
  int major, minor;
  int res = cuDeviceGetAttribute(&major, 75, device);
  if (res != 0)
    return std::make_tuple(res, -1, -1);

  res = cuDeviceGetAttribute(&minor, 76, device);
  if (res != 0)
    return std::make_tuple(res, -1, -1);

  return std::make_tuple(0, major, minor);
}

std::pair<int, int> closest_divisor(int val, int div) {
  if (div == 2) {
    if ((val & 1) == 0) { return std::make_pair(2, val >> 1);  }
    else                { return std::make_pair(1, val);       }
  }
  else if (div == 4) {
    if      ((val & 3) == 0) { return std::make_pair(4, val >> 2); }
    else if ((val % 3) == 0) { return std::make_pair(3, val / 3);  }
    else if ((val % 5) == 0) { return std::make_pair(5, val / 5);  }
    else if ((val & 1) == 0) { return std::make_pair(2, val >> 1); }
    else if ((val % 7) == 0) { return std::make_pair(7, val / 7);  }
    else                     { return std::make_pair(1, val);      }
  }
}

std::string get_op_string(bool a_t, bool b_t) {
  if      (!a_t && !b_t) return "NN";
  else if (a_t && !b_t)  return "TN";
  else if (!a_t && b_t)  return "NT";
  else                   return "TT";
}

bool gemm(std::string precision, void *A, void *B, void *C,
          bool a_t, bool b_t,
          int m, int n, int k,
          int lda, int ldb, int ldc,
          float alpha, float beta,
          CUstream stream, unsigned int grid, unsigned int shared) {
  std::string kernel_op = get_op_string(a_t, b_t);

  if (grid >= selections[precision][kernel_op].size())
    return false;

  kernel_properties kp = selections[precision][kernel_op][grid];

  if (shared >= kp.shared_sizes.size())
    return false;

  bool vec4A, vec8A;
  bool vec4B, vec8B;
  if (a_t) {
    vec4A = (lda & 3) == 0 && (m & 3) == 0; //multiple of 4
    vec8A = (lda & 7) == 0 && (m & 7) == 0; //multiple of 8
  }
  else {
    vec4A = (lda & 3) == 0 && (k & 3) == 0; //multiple of 4
    vec8A = (lda & 7) == 0 && (k & 7) == 0; //multiple of 8
  }

  if (b_t) {
    vec4B = (ldb & 3) == 0 && (k & 3) == 0; //multiple of 4
    vec8B = (ldb & 7) == 0 && (k & 7) == 0; //multiple of 8
  }
  else {
    vec4B = (ldb & 3) == 0 && (n & 3) == 0; //multiple of 4
    vec8B = (ldb & 7) == 0 && (n & 7) == 0; //multiple of 8
  }

  bool vec4C = (ldc & 3) == 0 && (n & 3) == 0;

  bool vecA = (kp.vA == 4 && vec4A) || (kp.vA == 8 && vec8A);
  bool vecB = (kp.vB == 4 && vec4B) || (kp.vB == 8 && vec8B);
  bool vecC = kp.vC == 1 || vec4C;

  bool vec = vecA && vecB && vecC;

  CUdevice device;
  int res = cuCtxGetDevice(&device);
  if (res != 0)
    return false;

  bool success;
  int major, minor;

  std::tie(success, major, minor) = getDeviceProperties(device);

  if (success != 0)
    return false;

  std::string kernel_string;
  kernel_string.reserve(64);

  kernel_string += precision + "gemm_" + kp.tile_string +
                   "_" + kernel_op;
  if (vec)
    kernel_string += "_vec";

  if (major == 5)
    kernel_string += "_sm_50";
  else if (major == 6)
    kernel_string += "_sm_60";
  else
    return false;

  auto kernel = kernels_.find(kernel_string);
  if (kernel == kernels_.end()) {
    loadKernels(major);
    kernel = kernels_.find(kernel_string);
  }

  int blk_A = (m + kp.tile_m - 1) / kp.tile_m;
  int blk_B = (n + kp.tile_n - 1) / kp.tile_n;

  int blk_a, blk_b;
  std::tie(blk_a, blk_A) = closest_divisor(blk_A, kp.div);
  std::tie(blk_b, blk_B) = closest_divisor(blk_B, kp.div);

  if (blk_a == 1)
    std::tie(blk_a, blk_A) = std::make_pair(blk_A, 1);

  void *args[13] = {&C, &A, &B, &alpha, &beta, &lda, &ldb, &ldc,
                    &m, &n, &k, &blk_a, &blk_b};

  res = cuLaunchKernel(kernel->second, blk_a * blk_b, blk_B, blk_A,
                       kp.threads, 1, 1,
                       kp.shared_sizes[shared], stream, args, NULL);

  if (res != 0) {
    std::cerr << "Failed to execute " << kernel_string << " " <<
      res << std::endl;
    return false;
  }

  return true;
}

};

bool get_grid_limits(char precision, bool a_t, bool b_t, unsigned int *grid)
{
  std::string prec_string(1, precision);

  *grid = selections[prec_string][get_op_string(a_t, b_t)].size();
  return true;
}

bool get_shared_limits(char precision, bool a_t, bool b_t, unsigned int grid, unsigned int *shared) {
  std::string prec_string(1, precision);

  if (grid >= selections[prec_string][get_op_string(a_t, b_t)].size())
    return false;

  *shared = selections[prec_string][get_op_string(a_t, b_t)][grid].shared_sizes.size();

  return true;
}

bool openai_sgemm(float *A, float *B, float *C,
           bool a_t, bool b_t,
           int m, int n, int k,
           int lda, int ldb, int ldc,
           float alpha, float beta,
           CUstream stream, unsigned int grid, unsigned int shared) {
  return gemm("s",
              static_cast<void*>(A),
              static_cast<void*>(B),
              static_cast<void*>(C),
              a_t, b_t, m, n, k, lda, ldb, ldc,
              alpha, beta, stream, grid, shared);
}

bool openai_hgemm(uint16_t *A, uint16_t *B, uint16_t *C,
           bool a_t, bool b_t,
           int m, int n, int k,
           int lda, int ldb, int ldc,
           float alpha, float beta,
           CUstream stream, unsigned int grid, unsigned int shared) {
  return gemm("h",
              static_cast<void*>(A),
              static_cast<void*>(B),
              static_cast<void*>(C),
              a_t, b_t, m, n, k, lda, ldb, ldc,
              alpha, beta, stream, grid, shared);
}
<|endoftext|>


<commit_before><commit_msg>Fixed typo in comment<commit_after><|endoftext|>


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

#include "rtkCudaLastDimensionTVDenoisingImageFilter.h"
#include "rtkCudaLastDimensionTVDenoisingImageFilter.hcu"

#include <itkMacro.h>

rtk::CudaLastDimensionTVDenoisingImageFilter
::CudaLastDimensionTVDenoisingImageFilter()
{
}

void
rtk::CudaLastDimensionTVDenoisingImageFilter
::GPUGenerateData()
{
  std::cout << "Performing temporal TV regul" << std::endl;

  this->GetOutput()->SetRegions(this->GetOutput()->GetLargestPossibleRegion());
  this->GetOutput()->Allocate();

  int inputSize[4];
  int outputSize[4];

  for (int i=0; i<4; i++)
    {
    inputSize[i] = this->GetInput()->GetBufferedRegion().GetSize()[i];
    outputSize[i] = this->GetOutput()->GetBufferedRegion().GetSize()[i];

    if (inputSize[i] != outputSize[i])
      itkGenericExceptionMacro(<< "The CUDA Last Dimension Total Variation Denoising filter can only handle input and output regions of equal size");
    }

  float *pin = *(float**)( this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer() );
  float *pout = *(float**)( this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer() );

  CUDA_total_variation_last_dimension(inputSize,
                                     pin,
                                     pout,
                                     static_cast<float>(m_Gamma),
                                     static_cast<float>(m_Beta),
                                     m_NumberOfIterations);
}
<commit_msg>Removed unnecessary std::cout<commit_after>/*=========================================================================
 *
 *  Copyright RTK Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

#include "rtkCudaLastDimensionTVDenoisingImageFilter.h"
#include "rtkCudaLastDimensionTVDenoisingImageFilter.hcu"

#include <itkMacro.h>

rtk::CudaLastDimensionTVDenoisingImageFilter
::CudaLastDimensionTVDenoisingImageFilter()
{
}

void
rtk::CudaLastDimensionTVDenoisingImageFilter
::GPUGenerateData()
{
  this->GetOutput()->SetRegions(this->GetOutput()->GetLargestPossibleRegion());
  this->GetOutput()->Allocate();

  int inputSize[4];
  int outputSize[4];

  for (int i=0; i<4; i++)
    {
    inputSize[i] = this->GetInput()->GetBufferedRegion().GetSize()[i];
    outputSize[i] = this->GetOutput()->GetBufferedRegion().GetSize()[i];

    if (inputSize[i] != outputSize[i])
      itkGenericExceptionMacro(<< "The CUDA Last Dimension Total Variation Denoising filter can only handle input and output regions of equal size");
    }

  float *pin = *(float**)( this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer() );
  float *pout = *(float**)( this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer() );

  CUDA_total_variation_last_dimension(inputSize,
                                     pin,
                                     pout,
                                     static_cast<float>(m_Gamma),
                                     static_cast<float>(m_Beta),
                                     m_NumberOfIterations);
}
<|endoftext|>