<commit_before>/*
 * Copyright (c) 2017-2018 dresden elektronik ingenieurtechnik gmbh.
 * All rights reserved.
 *
 * The software in this package is published under the terms of the BSD
 * style license a copy of which has been included with this distribution in
 * the LICENSE.txt file.
 *
 */

#ifdef USE_WEBSOCKETS

#include "deconz/dbg_trace.h"
#include "websocket_server.h"

/*! Constructor.
 */
WebSocketServer::WebSocketServer(QObject *parent, quint16 port) :
    QObject(parent)
{
    srv = new QWebSocketServer("deconz", QWebSocketServer::NonSecureMode, this);

    quint16 p = 0;
    quint16 ports[] = { 443, 443, 8080, 8088, 20877, 0 }; // start with proxy frinedly ports first, use random port as fallback
    if (port > 0)
    {
        ports[0] = port;
    }

    while (!srv->listen(QHostAddress::AnyIPv4, ports[p]))
    {
        if (ports[p] == 0)
        {
            DBG_Printf(DBG_ERROR, "giveup starting websocket server on port %u. error: %s\n", ports[p], qPrintable(srv->errorString()));
            break;
        }

        DBG_Printf(DBG_ERROR, "failed to start websocket server on port %u. error: %s\n", ports[p], qPrintable(srv->errorString()));
        p++;
    }

    if (srv->isListening())
    {
        DBG_Printf(DBG_INFO, "started websocket server at port %u\n", srv->serverPort());
        connect(srv, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
    }
}

/*! Returns the websocket server port.
    \return the active server port, or 0 if not active
 */
quint16 WebSocketServer::port() const
{
    return srv->isListening() ? srv->serverPort() : 0;
}

/*! Handler for new client connections.
 */
void WebSocketServer::onNewConnection()
{
    while (srv->hasPendingConnections())
    {
        QWebSocket *sock = srv->nextPendingConnection();
        DBG_Printf(DBG_INFO, "New websocket %s:%u (state: %d) \n", qPrintable(sock->peerAddress().toString()), sock->peerPort(), sock->state());
        connect(sock, SIGNAL(disconnected()), this, SLOT(onSocketDisconnected()));
        connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onSocketError(QAbstractSocket::SocketError)));
        clients.push_back(sock);
    }
}

/*! Handle websocket disconnected signal.
 */
void WebSocketServer::onSocketDisconnected()
{
    for (size_t i = 0; i < clients.size(); i++)
    {
        QWebSocket *sock = qobject_cast<QWebSocket*>(sender());
        DBG_Assert(sock);
        if (sock && clients[i] == sock)
        {
            DBG_Printf(DBG_INFO, "Websocket disconnected %s:%u, state: %d, close-code: %d, reason: %s\n", qPrintable(sock->peerAddress().toString()), sock->peerPort(), sock->state(), sock->closeCode(), qPrintable(sock->closeReason()));
            sock->deleteLater();
            clients[i] = clients.back();
            clients.pop_back();
        }
    }
}

/*! Handle websocket error signal.
    \param err - the error which occured
 */
void WebSocketServer::onSocketError(QAbstractSocket::SocketError err)
{
    Q_UNUSED(err);
    for (size_t i = 0; i < clients.size(); i++)
    {
        QWebSocket *sock = qobject_cast<QWebSocket*>(sender());
        DBG_Assert(sock);
        if (sock && clients[i] == sock)
        {
            DBG_Printf(DBG_INFO, "Remove websocket %s:%u after error %s, close-code: %d, reason: %s\n",
                       qPrintable(sock->peerAddress().toString()), sock->peerPort(), qPrintable(sock->errorString()), sock->closeCode(), qPrintable(sock->closeReason()));
            sock->deleteLater();
            clients[i] = clients.back();
            clients.pop_back();
        }
    }
}

/*! Broadcasts a message to all connected clients.
    \param msg the message as JSON string
 */
void WebSocketServer::broadcastTextMessage(const QString &msg)
{
    for (size_t i = 0; i < clients.size(); i++)
    {
        QWebSocket *sock = clients[i];

        if (sock->state() != QAbstractSocket::ConnectedState)
        {
            DBG_Printf(DBG_INFO, "Websocket %s:%u unexpected state: %d\n", qPrintable(sock->peerAddress().toString()), sock->peerPort(), sock->state());
        }

        qint64 ret = sock->sendTextMessage(msg);
        DBG_Printf(DBG_INFO_L2, "Websocket %s:%u send message: %s (ret = %d)\n", qPrintable(sock->peerAddress().toString()), sock->peerPort(), qPrintable(msg), ret);
        sock->flush();
    }
}

/*! Flush the sockets of all connected clients.
 */
void WebSocketServer::flush()
{
    for (size_t i = 0; i < clients.size(); i++)
    {
        QWebSocket *sock = clients[i];

        if (sock->state() == QAbstractSocket::ConnectedState)
        {
            sock->flush();
        }
    }
}

#else // no websockets
  WebSocketServer::WebSocketServer(QObject *parent) :
      QObject(parent)
  { }
  void WebSocketServer::onNewConnection() { }
  void WebSocketServer::broadcastTextMessage(const QString &) { }
  quint16 WebSocketServer::port() const {  return 0; }
#endif
<commit_msg>Enable websocket server to listen on IP specified<commit_after>/*
 * Copyright (c) 2017-2018 dresden elektronik ingenieurtechnik gmbh.
 * All rights reserved.
 *
 * The software in this package is published under the terms of the BSD
 * style license a copy of which has been included with this distribution in
 * the LICENSE.txt file.
 *
 */

#ifdef USE_WEBSOCKETS

#include "de_web_plugin.h"
#include "de_web_plugin_private.h"
#include "deconz/dbg_trace.h"
#include "websocket_server.h"

/*! Constructor.
 */
WebSocketServer::WebSocketServer(QObject *parent, quint16 port) :
    QObject(parent)
{
    srv = new QWebSocketServer("deconz", QWebSocketServer::NonSecureMode, this);

    quint16 p = 0;
    quint16 ports[] = { 443, 443, 8080, 8088, 20877, 0 }; // start with proxy frinedly ports first, use random port as fallback
    if (port > 0)
    {
        ports[0] = port;
    }

    QHostAddress address;
    if (deCONZ::appArgumentString("--http-listen", 0).isEmpty()) // Tie websocket server to specified IP, if any
    {
        address = QHostAddress::AnyIPv4;
    }
    else
    {
        address = deCONZ::appArgumentString("--http-listen", 0);
    }

    while (!srv->listen(address, ports[p]))
    {
        if (ports[p] == 0)
        {
            DBG_Printf(DBG_ERROR, "Giveup starting websocket server on %s, port: %u. error: %s\n", qPrintable(address.toString()), ports[p], qPrintable(srv->errorString()));
            break;
        }

        DBG_Printf(DBG_ERROR, "Failed to start websocket server on %s, port: %u. error: %s\n", qPrintable(address.toString()), ports[p], qPrintable(srv->errorString()));
        p++;
    }

    if (srv->isListening())
    {
        DBG_Printf(DBG_INFO, "Started websocket server on %s, port: %u\n", qPrintable(address.toString()), srv->serverPort());
        connect(srv, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
    }
}

/*! Returns the websocket server port.
    \return the active server port, or 0 if not active
 */
quint16 WebSocketServer::port() const
{
    return srv->isListening() ? srv->serverPort() : 0;
}

/*! Handler for new client connections.
 */
void WebSocketServer::onNewConnection()
{
    while (srv->hasPendingConnections())
    {
        QWebSocket *sock = srv->nextPendingConnection();
        DBG_Printf(DBG_INFO, "New websocket %s:%u (state: %d) \n", qPrintable(sock->peerAddress().toString()), sock->peerPort(), sock->state());
        connect(sock, SIGNAL(disconnected()), this, SLOT(onSocketDisconnected()));
        connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onSocketError(QAbstractSocket::SocketError)));
        clients.push_back(sock);
    }
}

/*! Handle websocket disconnected signal.
 */
void WebSocketServer::onSocketDisconnected()
{
    for (size_t i = 0; i < clients.size(); i++)
    {
        QWebSocket *sock = qobject_cast<QWebSocket*>(sender());
        DBG_Assert(sock);
        if (sock && clients[i] == sock)
        {
            DBG_Printf(DBG_INFO, "Websocket disconnected %s:%u, state: %d, close-code: %d, reason: %s\n", qPrintable(sock->peerAddress().toString()), sock->peerPort(), sock->state(), sock->closeCode(), qPrintable(sock->closeReason()));
            sock->deleteLater();
            clients[i] = clients.back();
            clients.pop_back();
        }
    }
}

/*! Handle websocket error signal.
    \param err - the error which occured
 */
void WebSocketServer::onSocketError(QAbstractSocket::SocketError err)
{
    Q_UNUSED(err);
    for (size_t i = 0; i < clients.size(); i++)
    {
        QWebSocket *sock = qobject_cast<QWebSocket*>(sender());
        DBG_Assert(sock);
        if (sock && clients[i] == sock)
        {
            DBG_Printf(DBG_INFO, "Remove websocket %s:%u after error %s, close-code: %d, reason: %s\n",
                       qPrintable(sock->peerAddress().toString()), sock->peerPort(), qPrintable(sock->errorString()), sock->closeCode(), qPrintable(sock->closeReason()));
            sock->deleteLater();
            clients[i] = clients.back();
            clients.pop_back();
        }
    }
}

/*! Broadcasts a message to all connected clients.
    \param msg the message as JSON string
 */
void WebSocketServer::broadcastTextMessage(const QString &msg)
{
    for (size_t i = 0; i < clients.size(); i++)
    {
        QWebSocket *sock = clients[i];

        if (sock->state() != QAbstractSocket::ConnectedState)
        {
            DBG_Printf(DBG_INFO, "Websocket %s:%u unexpected state: %d\n", qPrintable(sock->peerAddress().toString()), sock->peerPort(), sock->state());
        }

        qint64 ret = sock->sendTextMessage(msg);
        DBG_Printf(DBG_INFO_L2, "Websocket %s:%u send message: %s (ret = %d)\n", qPrintable(sock->peerAddress().toString()), sock->peerPort(), qPrintable(msg), ret);
        sock->flush();
    }
}

/*! Flush the sockets of all connected clients.
 */
void WebSocketServer::flush()
{
    for (size_t i = 0; i < clients.size(); i++)
    {
        QWebSocket *sock = clients[i];

        if (sock->state() == QAbstractSocket::ConnectedState)
        {
            sock->flush();
        }
    }
}

#else // no websockets
  WebSocketServer::WebSocketServer(QObject *parent) :
      QObject(parent)
  { }
  void WebSocketServer::onNewConnection() { }
  void WebSocketServer::broadcastTextMessage(const QString &) { }
  quint16 WebSocketServer::port() const {  return 0; }
#endif
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017 koolkdev
 *
 * This software may be modified and distributed under the terms
 * of the MIT license.  See the LICENSE file for details.
 */

#include <cstdio>
#include <vector>
#include <fstream>
#include <memory>
#include <iostream>
#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>

#include <wfslib/WfsLib.h>

void dumpdir(const boost::filesystem::path& target, const std::shared_ptr<Directory>& dir, const boost::filesystem::path& path, bool verbos) {
	if (!boost::filesystem::exists(target / path)) {
		if (!boost::filesystem::create_directories(target / path)) {
			std::cerr << "Error: Failed to create directory " << (target / path) << std::endl;
			return;
		}
	}
	for (auto item : *dir) {
		boost::filesystem::path npath = path / item->GetRealName();
		if (verbos)
			std::cout << "Dumping " << npath << std::endl;
		if (item->IsDirectory()) dumpdir(target, std::dynamic_pointer_cast<Directory>(item), npath, verbos);
		else if (item->IsFile()) {
			auto file = std::dynamic_pointer_cast<File>(item);
			std::ofstream output_file((target / npath).string(), std::ios::binary | std::ios::out);
			size_t to_read = file->GetSize();
			File::stream stream(file);
			std::vector<char> data(0x2000);
			while (to_read > 0) {
				stream.read(&*data.begin(), std::min(data.size(), to_read));
				auto read = stream.gcount();
				if (read <= 0) {
					std::cerr << "Error: Failed to read " << npath << std::endl;
					break;
				}
				output_file.write((char*)&*data.begin(), read);
				to_read -= static_cast<size_t>(read);
			}
			output_file.close();
		}
		else {
			printf("Test\n");
		}
	}
}

int main(int argc, char *argv[]) {
	try {
		boost::program_options::options_description desc("Allowed options");
		std::string wfs_path;
		desc.add_options()
			("help", "produce help message")
			("input", boost::program_options::value<std::string>(), "input file")
			("output", boost::program_options::value<std::string>(), "ouput directory")
			("otp", boost::program_options::value<std::string>(), "otp file")
			("seeprom", boost::program_options::value<std::string>(), "seeprom file (required if usb)")
			("dump-path", boost::program_options::value<std::string>(&wfs_path)->default_value("/"), "directory to dump (default: \"/\")")
			("mlc", "device is mlc (default: device is usb)")
			("usb", "device is usb")
			("verbos", "verbos output")
			;

		boost::program_options::variables_map vm;
		boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm);
		boost::program_options::notify(vm);

		bool bad = false;
		if (!vm.count("input")) { std::cerr << "Missing input file (--input)" << std::endl; bad = true; }
		if (!vm.count("output")) { std::cerr << "Missing output directory (--output)" << std::endl; bad = true; }
		if (!vm.count("otp")) { std::cerr << "Missing otp file (--otp)" << std::endl; bad = true; }
		if ((!vm.count("seeprom") && !vm.count("mlc"))) { std::cerr << "Missing seeprom file (--seeprom)" << std::endl; bad = true; }
		if (vm.count("mlc") + vm.count("usb") > 1) { std::cerr << "Can't specify both --mlc and --usb" << std::endl; bad = true; }
		if (vm.count("help") || bad) {
			std::cout << "Usage: wfs-extract --input <input file> --output <output directory> --otp <opt path> [--seeprom <seeprom path>] [--mlc] [--usb] [--dump-path <directory to dump>] [--verbos]" << std::endl;
			std::cout << desc << "\n";
			return 1;
		}

		std::vector<uint8_t> key;
		std::unique_ptr<OTP> otp;
		// open otp
		try {
			otp.reset(OTP::LoadFromFile(vm["otp"].as<std::string>()));
		}
		catch (std::exception& e) {
			std::cerr << "Failed to open OTP: " << e.what() << std::endl;
			return 1;
		}

		if (vm.count("mlc")) {
			// mlc
			key = otp->GetMLCKey();
		}
		else {
			// usb
			std::unique_ptr<SEEPROM> seeprom;
			try {
				seeprom.reset(SEEPROM::LoadFromFile(vm["seeprom"].as<std::string>()));
			}
			catch (std::exception& e) {
				std::cerr << "Failed to open SEEPROM: " << e.what() << std::endl;
				return 1;
			}
			key = seeprom->GetUSBKey(*otp);
		}
		auto device = std::make_shared<FileDevice>(vm["input"].as<std::string>(), 9);
		Wfs::DetectDeviceSectorSizeAndCount(device, key);
		auto dir = Wfs(device, key).GetDirectory(vm["dump-path"].as<std::string>());
		if (!dir) {
			std::cerr << "Error: Didn't find directory " << vm["dump-path"].as<std::string>() << " in wfs" << std::endl;
			return 1;
		}
		std::cout << "Dumping..." << std::endl;
		dumpdir(boost::filesystem::path(vm["output"].as<std::string>()), dir, boost::filesystem::path(""), !!vm.count("verbos"));
		std::cout << "Done!" << std::endl;
	}
	catch (std::exception& e) {
		std::cerr << "Error: " << e.what() << std::endl;
		return 1;
	}
	return 0;
}<commit_msg>Undo accidental commit<commit_after>/*
 * Copyright (C) 2017 koolkdev
 *
 * This software may be modified and distributed under the terms
 * of the MIT license.  See the LICENSE file for details.
 */

#include <cstdio>
#include <vector>
#include <fstream>
#include <memory>
#include <iostream>
#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>

#include <wfslib/WfsLib.h>

void dumpdir(const boost::filesystem::path& target, const std::shared_ptr<Directory>& dir, const boost::filesystem::path& path, bool verbos) {
	if (!boost::filesystem::exists(target / path)) {
		if (!boost::filesystem::create_directories(target / path)) {
			std::cerr << "Error: Failed to create directory " << (target / path) << std::endl;
			return;
		}
	}
	for (auto item : *dir) {
		boost::filesystem::path npath = path / item->GetRealName();
		if (verbos)
			std::cout << "Dumping " << npath << std::endl;
		if (item->IsDirectory()) dumpdir(target, std::dynamic_pointer_cast<Directory>(item), npath, verbos);
		else if (item->IsFile()) {
			auto file = std::dynamic_pointer_cast<File>(item);
			std::ofstream output_file((target / npath).string(), std::ios::binary | std::ios::out);
			size_t to_read = file->GetSize();
			File::stream stream(file);
			std::vector<char> data(0x2000);
			while (to_read > 0) {
				stream.read(&*data.begin(), std::min(data.size(), to_read));
				auto read = stream.gcount();
				if (read <= 0) {
					std::cerr << "Error: Failed to read " << npath << std::endl;
					break;
				}
				output_file.write((char*)&*data.begin(), read);
				to_read -= static_cast<size_t>(read);
			}
			output_file.close();
		}
	}
}

int main(int argc, char *argv[]) {
	try {
		boost::program_options::options_description desc("Allowed options");
		std::string wfs_path;
		desc.add_options()
			("help", "produce help message")
			("input", boost::program_options::value<std::string>(), "input file")
			("output", boost::program_options::value<std::string>(), "ouput directory")
			("otp", boost::program_options::value<std::string>(), "otp file")
			("seeprom", boost::program_options::value<std::string>(), "seeprom file (required if usb)")
			("dump-path", boost::program_options::value<std::string>(&wfs_path)->default_value("/"), "directory to dump (default: \"/\")")
			("mlc", "device is mlc (default: device is usb)")
			("usb", "device is usb")
			("verbos", "verbos output")
			;

		boost::program_options::variables_map vm;
		boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm);
		boost::program_options::notify(vm);

		bool bad = false;
		if (!vm.count("input")) { std::cerr << "Missing input file (--input)" << std::endl; bad = true; }
		if (!vm.count("output")) { std::cerr << "Missing output directory (--output)" << std::endl; bad = true; }
		if (!vm.count("otp")) { std::cerr << "Missing otp file (--otp)" << std::endl; bad = true; }
		if ((!vm.count("seeprom") && !vm.count("mlc"))) { std::cerr << "Missing seeprom file (--seeprom)" << std::endl; bad = true; }
		if (vm.count("mlc") + vm.count("usb") > 1) { std::cerr << "Can't specify both --mlc and --usb" << std::endl; bad = true; }
		if (vm.count("help") || bad) {
			std::cout << "Usage: wfs-extract --input <input file> --output <output directory> --otp <opt path> [--seeprom <seeprom path>] [--mlc] [--usb] [--dump-path <directory to dump>] [--verbos]" << std::endl;
			std::cout << desc << "\n";
			return 1;
		}

		std::vector<uint8_t> key;
		std::unique_ptr<OTP> otp;
		// open otp
		try {
			otp.reset(OTP::LoadFromFile(vm["otp"].as<std::string>()));
		}
		catch (std::exception& e) {
			std::cerr << "Failed to open OTP: " << e.what() << std::endl;
			return 1;
		}

		if (vm.count("mlc")) {
			// mlc
			key = otp->GetMLCKey();
		}
		else {
			// usb
			std::unique_ptr<SEEPROM> seeprom;
			try {
				seeprom.reset(SEEPROM::LoadFromFile(vm["seeprom"].as<std::string>()));
			}
			catch (std::exception& e) {
				std::cerr << "Failed to open SEEPROM: " << e.what() << std::endl;
				return 1;
			}
			key = seeprom->GetUSBKey(*otp);
		}
		auto device = std::make_shared<FileDevice>(vm["input"].as<std::string>(), 9);
		Wfs::DetectDeviceSectorSizeAndCount(device, key);
		auto dir = Wfs(device, key).GetDirectory(vm["dump-path"].as<std::string>());
		if (!dir) {
			std::cerr << "Error: Didn't find directory " << vm["dump-path"].as<std::string>() << " in wfs" << std::endl;
			return 1;
		}
		std::cout << "Dumping..." << std::endl;
		dumpdir(boost::filesystem::path(vm["output"].as<std::string>()), dir, boost::filesystem::path(""), !!vm.count("verbos"));
		std::cout << "Done!" << std::endl;
	}
	catch (std::exception& e) {
		std::cerr << "Error: " << e.what() << std::endl;
		return 1;
	}
	return 0;
}<|endoftext|>


<commit_before>#ifndef DUNE_STUFF_MATH_HH
#define DUNE_STUFF_MATH_HH

#include <vector>
#include <limits>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <boost/format.hpp>

namespace Stuff {

/** \todo DOCME **/
template <class SomeRangeType, class OtherRangeType >
static double colonProduct(    const SomeRangeType& arg1,
						const OtherRangeType& arg2 )
{
	dune_static_assert( SomeRangeType::cols == SomeRangeType::rows
			&& OtherRangeType::cols == OtherRangeType::rows
			&& int(OtherRangeType::cols) == int(SomeRangeType::rows), "RangeTypes_dont_fit" );

	double ret = 0.0;
	// iterators
	typedef typename SomeRangeType::ConstRowIterator
		ConstRowIteratorType;
	typedef typename SomeRangeType::row_type::ConstIterator
		ConstIteratorType;
	ConstRowIteratorType arg1RowItEnd = arg1.end();
	ConstRowIteratorType arg2RowItEnd = arg2.end();
	ConstRowIteratorType arg2RowIt = arg2.begin();
	for (   ConstRowIteratorType arg1RowIt = arg1.begin();
			arg1RowIt != arg1RowItEnd, arg2RowIt != arg2RowItEnd;
			++arg1RowIt, ++arg2RowIt ) {
		ConstIteratorType row1ItEnd = arg1RowIt->end();
		ConstIteratorType row2ItEnd = arg2RowIt->end();
		ConstIteratorType row2It = arg2RowIt->begin();
		for (   ConstIteratorType row1It = arg1RowIt->begin();
				row1It != row1ItEnd, row2It != row2ItEnd;
				++row1It, ++row2It ) {
			ret += *row1It * *row2It;
		}
	}
	return ret;
}

/**
 *  \brief  dyadic product
 *
 *          Implements \f$\left(arg_{1} \otimes arg_{2}\right)_{i,j}:={arg_{1}}_{i} {arg_{2}}_{j}\f$
 *			RangeType1 should be fieldmatrix, RangeType2 fieldvector
 **/
template <class RangeType1, class RangeType2 >
static RangeType1 dyadicProduct(   const RangeType2& arg1,
								const RangeType2& arg2 )
{
	RangeType1 ret( 0.0 );
	typedef typename RangeType1::RowIterator
		MatrixRowIteratorType;
	typedef typename RangeType2::ConstIterator
		ConstVectorIteratorType;
	typedef typename RangeType2::Iterator
		VectorIteratorType;
	MatrixRowIteratorType rItEnd = ret.end();
	ConstVectorIteratorType arg1It = arg1.begin();
	for ( MatrixRowIteratorType rIt = ret.begin(); rIt != rItEnd; ++rIt ) {
		ConstVectorIteratorType arg2It = arg2.begin();
		VectorIteratorType vItEnd = rIt->end();
		for (   VectorIteratorType vIt = rIt->begin();
				vIt != vItEnd;
				++vIt ) {
			*vIt = *arg1It * *arg2It;
			++arg2It;
		}
		++arg1It;
	}
	return ret;
}

/** \brief a vector wrapper for continiously updating min,max,avg of some element type vector
  \todo find use? it's only used in minimal as testcase for itself...
  **/
template < class ElementType >
class MinMaxAvg {
	protected:
		typedef MinMaxAvg< ElementType >
			ThisType;
		typedef std::vector< ElementType >
			ElementsVec;
		typedef typename ElementsVec::const_iterator
			ElementsVecConstIterator;

	public:
		MinMaxAvg()
			: min_ ( std::numeric_limits< ElementType >::max() ),
			max_ ( std::numeric_limits< ElementType >::min() ),
			avg_ ( ( min_ + max_  ) / 2.0 )
		{}

		MinMaxAvg( const ElementsVec& elements )
		{
			for ( ElementsVecConstIterator it = elements.begin(); it != elements.end(); ++it ) {
				push( *it );
			}
		}

		ElementType min () const { return min_; }
		ElementType max () const { return max_; }
		ElementType average () const { return avg_; }

		void push( const ElementType& el ) {
			size_t num = elements_.size();
			elements_.push_back( el );
			max_ = std::max( el, max_ );
			min_ = std::min( el, min_ );
			if ( num > 0 ) {
				avg_ *= ( num / double( num + 1 ) );
				avg_ += (  el / double( num + 1 ) );
			}
			else {
				avg_ = el;
			}
		}

		template < class Stream >
		void output( Stream& stream ) {
			stream << boost::format( "min: %e\tmax: %e\tavg: %e\n" ) % min_ % max_ % avg_;
		}

	protected:
		ElementsVec elements_;
		ElementType min_,max_,avg_;

		MinMaxAvg( const ThisType& other );
};

//! bound \param var in [\param min,\param max]
template <typename T> T clamp(const T var,const T min,const T max)
{
	return ( (var < min) ? min : ( var > max ) ? max : var );
}

//! docme
class MovingAverage
{
	double avg_;
	size_t steps_;
public:
	MovingAverage()
		:avg_(0.0),steps_(0)
	{}
	MovingAverage& operator += (double val)
	{
		avg_ += ( val - avg_ ) / ++steps_;
		return *this;
	}
	operator double () { return avg_; }
};

//! no-branch sign function
long sign(long x) { return long(x!=0) | (long(x>=0)-1);  }

} //end namespace Stuff

#endif // DUNE_STUFF_MATH_HH
<commit_msg>move MinMaxAvg to boost::accumulator based implementation<commit_after>#ifndef DUNE_STUFF_MATH_HH
#define DUNE_STUFF_MATH_HH

#include <vector>
#include <limits>
#include <algorithm>
#include <cstring>
#include <iostream>
#include "static_assert.hh"
#include <boost/format.hpp>
#include <boost/static_assert.hpp>
#include <boost/fusion/include/void.hpp>
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/max.hpp>
#include <boost/accumulators/statistics/min.hpp>
#include <boost/accumulators/statistics/mean.hpp>

namespace Stuff {

/** \todo DOCME **/
template <class SomeRangeType, class OtherRangeType >
static double colonProduct(    const SomeRangeType& arg1,
						const OtherRangeType& arg2 )
{
	dune_static_assert( SomeRangeType::cols == SomeRangeType::rows
			&& OtherRangeType::cols == OtherRangeType::rows
			&& int(OtherRangeType::cols) == int(SomeRangeType::rows), "RangeTypes_dont_fit" );

	double ret = 0.0;
	// iterators
	typedef typename SomeRangeType::ConstRowIterator
		ConstRowIteratorType;
	typedef typename SomeRangeType::row_type::ConstIterator
		ConstIteratorType;
	ConstRowIteratorType arg1RowItEnd = arg1.end();
	ConstRowIteratorType arg2RowItEnd = arg2.end();
	ConstRowIteratorType arg2RowIt = arg2.begin();
	for (   ConstRowIteratorType arg1RowIt = arg1.begin();
			arg1RowIt != arg1RowItEnd, arg2RowIt != arg2RowItEnd;
			++arg1RowIt, ++arg2RowIt ) {
		ConstIteratorType row1ItEnd = arg1RowIt->end();
		ConstIteratorType row2ItEnd = arg2RowIt->end();
		ConstIteratorType row2It = arg2RowIt->begin();
		for (   ConstIteratorType row1It = arg1RowIt->begin();
				row1It != row1ItEnd, row2It != row2ItEnd;
				++row1It, ++row2It ) {
			ret += *row1It * *row2It;
		}
	}
	return ret;
}

/**
 *  \brief  dyadic product
 *
 *          Implements \f$\left(arg_{1} \otimes arg_{2}\right)_{i,j}:={arg_{1}}_{i} {arg_{2}}_{j}\f$
 *			RangeType1 should be fieldmatrix, RangeType2 fieldvector
 **/
template <class RangeType1, class RangeType2 >
static RangeType1 dyadicProduct(   const RangeType2& arg1,
								const RangeType2& arg2 )
{
	RangeType1 ret( 0.0 );
	typedef typename RangeType1::RowIterator
		MatrixRowIteratorType;
	typedef typename RangeType2::ConstIterator
		ConstVectorIteratorType;
	typedef typename RangeType2::Iterator
		VectorIteratorType;
	MatrixRowIteratorType rItEnd = ret.end();
	ConstVectorIteratorType arg1It = arg1.begin();
	for ( MatrixRowIteratorType rIt = ret.begin(); rIt != rItEnd; ++rIt ) {
		ConstVectorIteratorType arg2It = arg2.begin();
		VectorIteratorType vItEnd = rIt->end();
		for (   VectorIteratorType vIt = rIt->begin();
				vIt != vItEnd;
				++vIt ) {
			*vIt = *arg1It * *arg2It;
			++arg2It;
		}
		++arg1It;
	}
	return ret;
}

/** \brief a vector wrapper for continiously updating min,max,avg of some element type vector
  \todo find use? it's only used in minimal as testcase for itself...
  **/
template < class ElementType >
class MinMaxAvg {
	protected:
		typedef MinMaxAvg< ElementType >
			ThisType;
		typedef std::vector< ElementType >
			ElementsVec;
		typedef typename ElementsVec::const_iterator
			ElementsVecConstIterator;

	public:
		MinMaxAvg()
		{}

		template < class stl_container_type >
		MinMaxAvg( const stl_container_type& elements )
		{
			dune_static_assert( (boost::is_same< ElementType, typename stl_container_type::value_type >::value),
								 "cannot assign mismatching types" );
			acc_ = std::for_each( elements.begin(), elements.end(), acc_ );
		}

		ElementType min () const { return boost::accumulators::min(acc_); }
		ElementType max () const { return boost::accumulators::max(acc_); }
		ElementType average () const { return boost::accumulators::mean(acc_); }

		void push( const ElementType& el ) {
			acc_( el );
		}

		template < class Stream >
		void output( Stream& stream ) {
			stream << boost::format( "min: %e\tmax: %e\tavg: %e\n" ) % min() % max() % average();
		}

	protected:
		typedef boost::accumulators::stats<
				boost::accumulators::tag::max,
				boost::accumulators::tag::min,
				boost::accumulators::tag::mean >
			StatsType;
		boost::accumulators::accumulator_set< ElementType,StatsType > acc_;

		MinMaxAvg( const ThisType& other );
};

//! bound \param var in [\param min,\param max]
template <typename T> T clamp(const T var,const T min,const T max)
{
	return ( (var < min) ? min : ( var > max ) ? max : var );
}

//! docme
class MovingAverage
{
	double avg_;
	size_t steps_;
public:
	MovingAverage()
		:avg_(0.0),steps_(0)
	{}
	MovingAverage& operator += (double val)
	{
		avg_ += ( val - avg_ ) / ++steps_;
		return *this;
	}
	operator double () { return avg_; }
};

//! no-branch sign function
long sign(long x) { return long(x!=0) | (long(x>=0)-1);  }

} //end namespace Stuff

#endif // DUNE_STUFF_MATH_HH
<|endoftext|>


<commit_before><commit_msg>fdo#46808, Remove unnecessary call to getProcessServiceFactory<commit_after><|endoftext|>


<commit_before>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.

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 <Python.h>
#include <fstream>
#include <vector>

#include "paddle/framework/net.h"
#include "paddle/framework/op_registry.h"
#include "paddle/framework/operator.h"
#include "paddle/framework/scope.h"
#include "paddle/platform/enforce.h"
#include "paddle/platform/place.h"
#include "paddle/pybind/tensor_bind.h"
#include "pybind11/numpy.h"
#include "pybind11/pybind11.h"
#include "pybind11/stl.h"

namespace py = pybind11;
namespace pd = paddle::framework;

USE_OP(add_two);
USE_OP(onehot_cross_entropy);
USE_OP_WITHOUT_KERNEL(fc);
USE_OP(sgd);
USE_OP(mul);
USE_OP(mean);
USE_OP(sigmoid);
USE_OP(softmax);
USE_OP(rowwise_add);
USE_OP_WITHOUT_KERNEL(recurrent_op);

template <typename ClassType>
void ExposeOperator(ClassType& m) {
  m.def("infer_shape", &ClassType::type::InferShape)
      .def("run", &ClassType::type::Run)
      .def("outputs",
           [](const typename ClassType::type& op) -> std::vector<std::string> {
             return op.outputs_;
           })
      .def("__str__", &ClassType::type::DebugString);
}

static size_t UniqueIntegerGenerator() {
  static std::atomic<size_t> generator;
  return generator.fetch_add(1);
}

bool IsCompileGPU() {
#ifdef PADDLE_ONLY_CPU
  return false;
#else
  return true;
#endif
}

PYBIND11_PLUGIN(core) {
  py::module m("core", "C++ core of PaddlePaddle");

  py::class_<pd::Tensor>(m, "Tensor", py::buffer_protocol())
      .def_buffer([](pd::Tensor& self) -> py::buffer_info {
        return paddle::pybind::CastToPyBuffer(self);
      })
      .def("get_dims",
           [](const pd::Tensor& self) { return pd::vectorize(self.dims()); })
      .def("set_dims",
           [](pd::Tensor& self, const std::vector<int>& dim) {
             self.Resize(pd::make_ddim(dim));
           })
      .def("alloc_float",
           [](pd::Tensor& self, paddle::platform::GPUPlace& place) {
             self.mutable_data<float>(place);
           })
      .def("alloc_float",
           [](pd::Tensor& self, paddle::platform::CPUPlace& place) {
             self.mutable_data<float>(place);
           })
      .def("alloc_int",
           [](pd::Tensor& self, paddle::platform::CPUPlace& place) {
             self.mutable_data<int>(place);
           })
      .def("alloc_int",
           [](pd::Tensor& self, paddle::platform::GPUPlace& place) {
             self.mutable_data<int>(place);
           })
      .def("set", paddle::pybind::PyCPUTensorSetFromArray<float>)
      .def("set", paddle::pybind::PyCPUTensorSetFromArray<int>)
#ifndef PADDLE_ONLY_CPU
      .def("set", paddle::pybind::PyCUDATensorSetFromArray<float>)
      .def("set", paddle::pybind::PyCUDATensorSetFromArray<int>)
#endif
      .def("shape",
           [](pd::Tensor& self) { return pd::vectorize(self.dims()); });

  py::class_<pd::Variable>(m, "Variable", R"DOC(Variable Class.

All parameter, weight, gradient are variables in Paddle.
)DOC")
      .def("is_int", [](const pd::Variable& var) { return var.IsType<int>(); })
      .def("set_int",
           [](pd::Variable& var, int val) -> void {
             *var.GetMutable<int>() = val;
           })
      .def("get_int",
           [](const pd::Variable& var) -> int { return var.Get<int>(); })
      .def("get_tensor",
           [](pd::Variable& self) -> pd::Tensor* {
             return self.GetMutable<pd::Tensor>();
           },
           py::return_value_policy::reference)
      .def("get_net",
           [](pd::Variable& self) -> pd::NetOp* {
             return self.GetMutable<pd::NetOp>();
           },
           py::return_value_policy::reference);

  py::class_<pd::Scope>(m, "Scope", "")
      .def("new_var",
           [](pd::Scope& self, const std::string& name) -> pd::Variable* {
             return self.NewVar(name);
           },
           py::return_value_policy::reference)
      .def("find_var", &pd::Scope::FindVar, py::return_value_policy::reference)
      .def(py::init<>())
      .def("new_scope",
           [](pd::Scope& self) -> pd::Scope* { return &self.NewScope(); },
           py::return_value_policy::reference)
      .def("drop_kids", &pd::Scope::DropKids);

  //! @note: Be careful! PyBind will return std::string as an unicode, not
  //! Python str. If you want a str object, you should cast them in Python.
  m.def("get_all_op_protos", []() -> std::vector<py::bytes> {
    auto& protos = pd::OpRegistry::protos();
    std::vector<py::bytes> ret_values;
    for (auto it = protos.begin(); it != protos.end(); ++it) {
      PADDLE_ENFORCE(it->second.IsInitialized(),
                     "OpProto must all be initialized");
      std::string str;
      PADDLE_ENFORCE(it->second.SerializeToString(&str),
                     "Serialize OpProto Error. This could be a bug of Paddle.");
      ret_values.push_back(py::bytes(str));
    }
    return ret_values;
  });
  m.def_submodule(
       "var_names",
       "The module will return special predefined variable name in Paddle")
      .def("empty", pd::OperatorBase::EMPTY_VAR_NAME)
      .def("temp", pd::OperatorBase::TMP_VAR_NAME);
  //clang-format off
  py::class_<paddle::platform::DeviceContext>(m, "DeviceContext")
      .def_static("create",
                  [](paddle::platform::CPUPlace& place)
                      -> paddle::platform::DeviceContext* {
                    return new paddle::platform::CPUDeviceContext();
                  })
      .def_static("create",
                  [](paddle::platform::GPUPlace& place)
                      -> paddle::platform::DeviceContext* {
#ifdef PADDLE_ONLY_CPU
                    PADDLE_THROW("GPUPlace is not supported in CPU device.");
#else
                    return new paddle::platform::CUDADeviceContext(place);
#endif
                  });
  //clang-format on

  py::class_<paddle::platform::GPUPlace>(m, "GPUPlace").def(py::init<int>());

  py::class_<paddle::platform::CPUPlace>(m, "CPUPlace").def(py::init<>());

  py::class_<pd::OperatorBase, std::shared_ptr<pd::OperatorBase>> operator_base(
      m, "Operator");

  operator_base.def_static("create", [](py::bytes protobin) {
    pd::OpDesc desc;
    PADDLE_ENFORCE(desc.ParsePartialFromString(protobin),
                   "Cannot parse user input to OpDesc");
    PADDLE_ENFORCE(desc.IsInitialized(),
                   "User OpDesc is not initialized, reason %s",
                   desc.InitializationErrorString());
    return pd::OpRegistry::CreateOp(desc);
  });
  ExposeOperator(operator_base);

  py::class_<pd::NetOp, std::shared_ptr<pd::NetOp>> net(m, "Net");

  net.def_static("create",
                 []() -> std::shared_ptr<pd::NetOp> {
                   auto retv = std::make_shared<pd::NetOp>();
                   retv->type_ = "plain_net";
                   return retv;
                 })
      .def("add_op", &pd::NetOp::AddOp)
      .def("add_op",
           [](pd::NetOp& self, const std::shared_ptr<pd::NetOp>& net) -> void {
             self.AddOp(std::static_pointer_cast<pd::OperatorBase>(net));
           })
      .def("complete_add_op", &pd::NetOp::CompleteAddOp)
      .def("complete_add_op",
           [](std::shared_ptr<pd::NetOp>& self) { self->CompleteAddOp(); });
  ExposeOperator(net);

  m.def("unique_integer", UniqueIntegerGenerator);

  m.def("is_compile_gpu", IsCompileGPU);

  return m.ptr();
}
<commit_msg>pass pre commit<commit_after>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.

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 <Python.h>
#include <fstream>
#include <vector>

#include "paddle/framework/net.h"
#include "paddle/framework/op_registry.h"
#include "paddle/framework/operator.h"
#include "paddle/framework/scope.h"
#include "paddle/platform/enforce.h"
#include "paddle/platform/place.h"
#include "paddle/pybind/tensor_bind.h"
#include "pybind11/numpy.h"
#include "pybind11/pybind11.h"
#include "pybind11/stl.h"

namespace py = pybind11;
namespace pd = paddle::framework;

USE_OP(add_two);
USE_OP(onehot_cross_entropy);
USE_OP_WITHOUT_KERNEL(fc);
USE_OP(sgd);
USE_OP(mul);
USE_OP(mean);
USE_OP(sigmoid);
USE_OP(softmax);
USE_OP(rowwise_add);
USE_OP_WITHOUT_KERNEL(recurrent_op);

template <typename ClassType>
void ExposeOperator(ClassType& m) {
  m.def("infer_shape", &ClassType::type::InferShape)
      .def("run", &ClassType::type::Run)
      .def("outputs",
           [](const typename ClassType::type& op) -> std::vector<std::string> {
             return op.outputs_;
           })
      .def("__str__", &ClassType::type::DebugString);
}

static size_t UniqueIntegerGenerator() {
  static std::atomic<size_t> generator;
  return generator.fetch_add(1);
}

bool IsCompileGPU() {
#ifdef PADDLE_ONLY_CPU
  return false;
#else
  return true;
#endif
}

PYBIND11_PLUGIN(core) {
  py::module m("core", "C++ core of PaddlePaddle");

  py::class_<pd::Tensor>(m, "Tensor", py::buffer_protocol())
      .def_buffer([](pd::Tensor& self) -> py::buffer_info {
        return paddle::pybind::CastToPyBuffer(self);
      })
      .def("get_dims",
           [](const pd::Tensor& self) { return pd::vectorize(self.dims()); })
      .def("set_dims",
           [](pd::Tensor& self, const std::vector<int>& dim) {
             self.Resize(pd::make_ddim(dim));
           })
      .def("alloc_float",
           [](pd::Tensor& self, paddle::platform::GPUPlace& place) {
             self.mutable_data<float>(place);
           })
      .def("alloc_float",
           [](pd::Tensor& self, paddle::platform::CPUPlace& place) {
             self.mutable_data<float>(place);
           })
      .def("alloc_int",
           [](pd::Tensor& self, paddle::platform::CPUPlace& place) {
             self.mutable_data<int>(place);
           })
      .def("alloc_int",
           [](pd::Tensor& self, paddle::platform::GPUPlace& place) {
             self.mutable_data<int>(place);
           })
      .def("set", paddle::pybind::PyCPUTensorSetFromArray<float>)
      .def("set", paddle::pybind::PyCPUTensorSetFromArray<int>)
#ifndef PADDLE_ONLY_CPU
      .def("set", paddle::pybind::PyCUDATensorSetFromArray<float>)
      .def("set", paddle::pybind::PyCUDATensorSetFromArray<int>)
#endif
      .def("shape",
           [](pd::Tensor& self) { return pd::vectorize(self.dims()); });

  py::class_<pd::Variable>(m, "Variable", R"DOC(Variable Class.

All parameter, weight, gradient are variables in Paddle.
)DOC")
      .def("is_int", [](const pd::Variable& var) { return var.IsType<int>(); })
      .def("set_int",
           [](pd::Variable& var, int val) -> void {
             *var.GetMutable<int>() = val;
           })
      .def("get_int",
           [](const pd::Variable& var) -> int { return var.Get<int>(); })
      .def("get_tensor",
           [](pd::Variable& self) -> pd::Tensor* {
             return self.GetMutable<pd::Tensor>();
           },
           py::return_value_policy::reference)
      .def("get_net",
           [](pd::Variable& self) -> pd::NetOp* {
             return self.GetMutable<pd::NetOp>();
           },
           py::return_value_policy::reference);

  py::class_<pd::Scope>(m, "Scope", "")
      .def("new_var",
           [](pd::Scope& self, const std::string& name) -> pd::Variable* {
             return self.NewVar(name);
           },
           py::return_value_policy::reference)
      .def("find_var", &pd::Scope::FindVar, py::return_value_policy::reference)
      .def(py::init<>())
      .def("new_scope",
           [](pd::Scope& self) -> pd::Scope* { return &self.NewScope(); },
           py::return_value_policy::reference)
      .def("drop_kids", &pd::Scope::DropKids);

  //! @note: Be careful! PyBind will return std::string as an unicode, not
  //! Python str. If you want a str object, you should cast them in Python.
  m.def("get_all_op_protos", []() -> std::vector<py::bytes> {
    auto& protos = pd::OpRegistry::protos();
    std::vector<py::bytes> ret_values;
    for (auto it = protos.begin(); it != protos.end(); ++it) {
      PADDLE_ENFORCE(it->second.IsInitialized(),
                     "OpProto must all be initialized");
      std::string str;
      PADDLE_ENFORCE(it->second.SerializeToString(&str),
                     "Serialize OpProto Error. This could be a bug of Paddle.");
      ret_values.push_back(py::bytes(str));
    }
    return ret_values;
  });
  m.def_submodule(
       "var_names",
       "The module will return special predefined variable name in Paddle")
      .def("empty", pd::OperatorBase::EMPTY_VAR_NAME)
      .def("temp", pd::OperatorBase::TMP_VAR_NAME);
  // clang-format off
  py::class_<paddle::platform::DeviceContext>(m, "DeviceContext")
      .def_static("create",
                  [](paddle::platform::CPUPlace& place)
                      -> paddle::platform::DeviceContext* {
                    return new paddle::platform::CPUDeviceContext();
                  })
      .def_static("create",
                  [](paddle::platform::GPUPlace& place)
                      -> paddle::platform::DeviceContext* {
#ifdef PADDLE_ONLY_CPU
                    PADDLE_THROW("GPUPlace is not supported in CPU device.");
#else
                    return new paddle::platform::CUDADeviceContext(place);
#endif
                  });
  // clang-format on

  py::class_<paddle::platform::GPUPlace>(m, "GPUPlace").def(py::init<int>());

  py::class_<paddle::platform::CPUPlace>(m, "CPUPlace").def(py::init<>());

  py::class_<pd::OperatorBase, std::shared_ptr<pd::OperatorBase>> operator_base(
      m, "Operator");

  operator_base.def_static("create", [](py::bytes protobin) {
    pd::OpDesc desc;
    PADDLE_ENFORCE(desc.ParsePartialFromString(protobin),
                   "Cannot parse user input to OpDesc");
    PADDLE_ENFORCE(desc.IsInitialized(),
                   "User OpDesc is not initialized, reason %s",
                   desc.InitializationErrorString());
    return pd::OpRegistry::CreateOp(desc);
  });
  ExposeOperator(operator_base);

  py::class_<pd::NetOp, std::shared_ptr<pd::NetOp>> net(m, "Net");

  net.def_static("create",
                 []() -> std::shared_ptr<pd::NetOp> {
                   auto retv = std::make_shared<pd::NetOp>();
                   retv->type_ = "plain_net";
                   return retv;
                 })
      .def("add_op", &pd::NetOp::AddOp)
      .def("add_op",
           [](pd::NetOp& self, const std::shared_ptr<pd::NetOp>& net) -> void {
             self.AddOp(std::static_pointer_cast<pd::OperatorBase>(net));
           })
      .def("complete_add_op", &pd::NetOp::CompleteAddOp)
      .def("complete_add_op",
           [](std::shared_ptr<pd::NetOp>& self) { self->CompleteAddOp(); });
  ExposeOperator(net);

  m.def("unique_integer", UniqueIntegerGenerator);

  m.def("is_compile_gpu", IsCompileGPU);

  return m.ptr();
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include "officecfg/Office/Common.hxx"

#include "comphelper/processfactory.hxx"

#include "osl/module.h"
#include "osl/process.h"

#include "rtl/ustrbuf.hxx"

#include "salinst.hxx"
#include "generic/gensys.h"
#include "generic/gendata.hxx"
#include "unx/desktops.hxx"
#include "vcl/printerinfomanager.hxx"

#include <cstdio>
#include <unistd.h>

using ::rtl::OUString;
using ::rtl::OUStringBuffer;
extern "C" {
typedef SalInstance*(*salFactoryProc)( oslModule pModule);
}

static oslModule pCloseModule = NULL;

static SalInstance* tryInstance( const OUString& rModuleBase, bool bForce = false )
{
    SalInstance* pInst = NULL;
#if !defined(ANDROID)
    if (!bForce && rModuleBase.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("gtk3")))
    {
        // Disable gtk3 plugin load except in experimental mode for now.
        using namespace com::sun::star;
        uno::Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
        if (!xContext.is() || !officecfg::Office::Common::Misc::ExperimentalMode::get(xContext))
            return NULL;
    }
#endif
    OUStringBuffer aModName( 128 );
    aModName.appendAscii( SAL_DLLPREFIX"vclplug_" );
    aModName.append( rModuleBase );
    aModName.appendAscii( SAL_DLLPOSTFIX );
    OUString aModule = aModName.makeStringAndClear();

    oslModule aMod = osl_loadModuleRelative(
        reinterpret_cast< oslGenericFunction >( &tryInstance ), aModule.pData,
        SAL_LOADMODULE_DEFAULT );
    if( aMod )
    {
        salFactoryProc aProc = (salFactoryProc)osl_getAsciiFunctionSymbol( aMod, "create_SalInstance" );
        if( aProc )
        {
            pInst = aProc( aMod );
#if OSL_DEBUG_LEVEL > 1
            std::fprintf( stderr, "sal plugin %s produced instance %p\n",
                     OUStringToOString( aModule, RTL_TEXTENCODING_ASCII_US ).getStr(),
                     pInst );
#endif
            if( pInst )
            {
                pCloseModule = aMod;

#ifndef ANDROID
                /*
                 * Recent GTK+ versions load their modules with RTLD_LOCAL, so we can
                 * not access the 'gnome_accessibility_module_shutdown' anymore.
                 * So make sure libgtk+ & co are still mapped into memory when
                 * atk-bridge's atexit handler gets called.
                 * #i109007# KDE3 seems to have the same problem.
		 * And same applies for KDE4.
                 */
                if( rModuleBase == "gtk" || rModuleBase == "gtk3" || rModuleBase == "tde" || rModuleBase == "kde" || rModuleBase == "kde4" )
                {
                    pCloseModule = NULL;
                }
#endif
                GetSalData()->m_pPlugin = aMod;
            }
            else
                osl_unloadModule( aMod );
        }
        else
        {
#if OSL_DEBUG_LEVEL > 1
            std::fprintf( stderr, "could not load symbol %s from shared object %s\n",
                     "create_SalInstance",
                     OUStringToOString( aModule, RTL_TEXTENCODING_ASCII_US ).getStr() );
#endif
            osl_unloadModule( aMod );
        }
    }
#if OSL_DEBUG_LEVEL > 1
    else
        std::fprintf( stderr, "could not load shared object %s\n",
                 OUStringToOString( aModule, RTL_TEXTENCODING_ASCII_US ).getStr() );
#endif

    return pInst;
}

#if !defined(ANDROID)

static DesktopType get_desktop_environment()
{
    OUStringBuffer aModName( 128 );
    aModName.appendAscii( SAL_DLLPREFIX"desktop_detector" );
    aModName.appendAscii( SAL_DLLPOSTFIX );
    OUString aModule = aModName.makeStringAndClear();

    oslModule aMod = osl_loadModuleRelative(
        reinterpret_cast< oslGenericFunction >( &tryInstance ), aModule.pData,
        SAL_LOADMODULE_DEFAULT );
    DesktopType ret = DESKTOP_UNKNOWN;
    if( aMod )
    {
        DesktopType (*pSym)() = (DesktopType(*)())
            osl_getAsciiFunctionSymbol( aMod, "get_desktop_environment" );
        if( pSym )
            ret = pSym();
    }
    osl_unloadModule( aMod );
    return ret;
}

#else

#define get_desktop_environment() DESKTOP_NONE // For now...

#endif

static SalInstance* autodetect_plugin()
{
    static const char* pTDEFallbackList[] =
    {
        "tde", "kde4", "kde", "gtk3", "gtk", "gen", 0
    };

    static const char* pKDEFallbackList[] =
    {
        "kde4", "kde", "gtk3", "gtk", "gen", 0
    };

    static const char* pStandardFallbackList[] =
    {
        "gtk3", "gtk", "gen", 0
    };

    static const char* pHeadlessFallbackList[] =
    {
        "svp", 0
    };

    DesktopType desktop = get_desktop_environment();
    const char ** pList = pStandardFallbackList;
    int nListEntry = 0;

    // no server at all: dummy plugin
    if ( desktop == DESKTOP_NONE )
        pList = pHeadlessFallbackList;
    else if ( desktop == DESKTOP_GNOME )
        pList = pStandardFallbackList;
    else if( desktop == DESKTOP_TDE )
        pList = pTDEFallbackList;
    else if( desktop == DESKTOP_KDE )
    {
        pList = pKDEFallbackList;
        nListEntry = 1;
    }
    else if( desktop == DESKTOP_KDE4 )
        pList = pKDEFallbackList;

    SalInstance* pInst = NULL;
    while( pList[nListEntry] && pInst == NULL )
    {
        rtl::OUString aTry( rtl::OUString::createFromAscii( pList[nListEntry] ) );
        pInst = tryInstance( aTry );
        #if OSL_DEBUG_LEVEL > 1
        if( pInst )
            std::fprintf( stderr, "plugin autodetection: %s\n", pList[nListEntry] );
        #endif
        nListEntry++;
    }

    return pInst;
}

static SalInstance* check_headless_plugin()
{
    int nParams = osl_getCommandArgCount();
    OUString aParam;
    for( int i = 0; i < nParams; i++ )
    {
        osl_getCommandArg( i, &aParam.pData );
        if( aParam == "-headless" || aParam == "--headless" )
        {
            return tryInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "svp" ) ) );
        }
    }
    return NULL;
}

SalInstance *CreateSalInstance()
{
    SalInstance*    pInst = NULL;

    static const char* pUsePlugin = getenv( "SAL_USE_VCLPLUGIN" );

    pInst = check_headless_plugin();

    if( !pInst && pUsePlugin && *pUsePlugin )
        pInst = tryInstance( OUString::createFromAscii( pUsePlugin ), true );

    if( ! pInst )
        pInst = autodetect_plugin();

    // fallback, try everything
    const char* pPlugin[] = { "gtk3", "gtk", "kde4", "kde", "tde", "gen", 0 };

    for ( int i = 0; !pInst && pPlugin[ i ]; ++i )
        pInst = tryInstance( OUString::createFromAscii( pPlugin[ i ] ) );

    if( ! pInst )
    {
        std::fprintf( stderr, "no suitable windowing system found, exiting.\n" );
        _exit( 1 );
    }

    // acquire SolarMutex
    pInst->AcquireYieldMutex( 1 );

    return pInst;
}

void DestroySalInstance( SalInstance *pInst )
{
    // release SolarMutex
    pInst->ReleaseYieldMutex();

    delete pInst;
    if( pCloseModule )
        osl_unloadModule( pCloseModule );
}

void InitSalData()
{
}

void DeInitSalData()
{
}

void InitSalMain()
{
}

void DeInitSalMain()
{
}

void SalAbort( const rtl::OUString& rErrorText, bool bDumpCore )
{
    if( rErrorText.isEmpty() )
        std::fprintf( stderr, "Application Error\n" );
    else
        std::fprintf( stderr, "%s\n", rtl::OUStringToOString(rErrorText, osl_getThreadTextEncoding()).getStr() );
    if( bDumpCore )
        abort();
    else
        _exit(1);
}

static const char * desktop_strings[] = { "none", "unknown", "GNOME", "TDE", "KDE", "KDE4" };

const OUString& SalGetDesktopEnvironment()
{
    static rtl::OUString aRet;
    if( aRet.isEmpty())
    {
        rtl::OUStringBuffer buf( 8 );
        buf.appendAscii( desktop_strings[ get_desktop_environment() ] );
        aRet = buf.makeStringAndClear();
    }
    return aRet;
}

SalData::SalData() :
    m_pInstance(NULL),
    m_pPlugin(NULL),
    m_pPIManager(NULL)
{
}

SalData::~SalData()
{
    psp::PrinterInfoManager::release();
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Enable experimental gtk3 plugin only via SAL_USE_VCLPLUGIN<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include "osl/module.h"
#include "osl/process.h"

#include "rtl/ustrbuf.hxx"

#include "salinst.hxx"
#include "generic/gensys.h"
#include "generic/gendata.hxx"
#include "unx/desktops.hxx"
#include "vcl/printerinfomanager.hxx"

#include <cstdio>
#include <unistd.h>

using ::rtl::OUString;
using ::rtl::OUStringBuffer;
extern "C" {
typedef SalInstance*(*salFactoryProc)( oslModule pModule);
}

static oslModule pCloseModule = NULL;

static SalInstance* tryInstance( const OUString& rModuleBase, bool bForce = false )
{
    SalInstance* pInst = NULL;
    // Disable gtk3 plugin for now unless explicitly requested via
    // SAL_USE_VCLPLUGIN=gtk3 (would ideally depend on experimental mode, but
    // reading the experimental mode setting requires the UNO service manager
    // which has not yet been instantiated):
    if (!bForce && rModuleBase.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("gtk3")))
    {
        return NULL;
    }
    OUStringBuffer aModName( 128 );
    aModName.appendAscii( SAL_DLLPREFIX"vclplug_" );
    aModName.append( rModuleBase );
    aModName.appendAscii( SAL_DLLPOSTFIX );
    OUString aModule = aModName.makeStringAndClear();

    oslModule aMod = osl_loadModuleRelative(
        reinterpret_cast< oslGenericFunction >( &tryInstance ), aModule.pData,
        SAL_LOADMODULE_DEFAULT );
    if( aMod )
    {
        salFactoryProc aProc = (salFactoryProc)osl_getAsciiFunctionSymbol( aMod, "create_SalInstance" );
        if( aProc )
        {
            pInst = aProc( aMod );
#if OSL_DEBUG_LEVEL > 1
            std::fprintf( stderr, "sal plugin %s produced instance %p\n",
                     OUStringToOString( aModule, RTL_TEXTENCODING_ASCII_US ).getStr(),
                     pInst );
#endif
            if( pInst )
            {
                pCloseModule = aMod;

#ifndef ANDROID
                /*
                 * Recent GTK+ versions load their modules with RTLD_LOCAL, so we can
                 * not access the 'gnome_accessibility_module_shutdown' anymore.
                 * So make sure libgtk+ & co are still mapped into memory when
                 * atk-bridge's atexit handler gets called.
                 * #i109007# KDE3 seems to have the same problem.
		 * And same applies for KDE4.
                 */
                if( rModuleBase == "gtk" || rModuleBase == "gtk3" || rModuleBase == "tde" || rModuleBase == "kde" || rModuleBase == "kde4" )
                {
                    pCloseModule = NULL;
                }
#endif
                GetSalData()->m_pPlugin = aMod;
            }
            else
                osl_unloadModule( aMod );
        }
        else
        {
#if OSL_DEBUG_LEVEL > 1
            std::fprintf( stderr, "could not load symbol %s from shared object %s\n",
                     "create_SalInstance",
                     OUStringToOString( aModule, RTL_TEXTENCODING_ASCII_US ).getStr() );
#endif
            osl_unloadModule( aMod );
        }
    }
#if OSL_DEBUG_LEVEL > 1
    else
        std::fprintf( stderr, "could not load shared object %s\n",
                 OUStringToOString( aModule, RTL_TEXTENCODING_ASCII_US ).getStr() );
#endif

    return pInst;
}

#if !defined(ANDROID)

static DesktopType get_desktop_environment()
{
    OUStringBuffer aModName( 128 );
    aModName.appendAscii( SAL_DLLPREFIX"desktop_detector" );
    aModName.appendAscii( SAL_DLLPOSTFIX );
    OUString aModule = aModName.makeStringAndClear();

    oslModule aMod = osl_loadModuleRelative(
        reinterpret_cast< oslGenericFunction >( &tryInstance ), aModule.pData,
        SAL_LOADMODULE_DEFAULT );
    DesktopType ret = DESKTOP_UNKNOWN;
    if( aMod )
    {
        DesktopType (*pSym)() = (DesktopType(*)())
            osl_getAsciiFunctionSymbol( aMod, "get_desktop_environment" );
        if( pSym )
            ret = pSym();
    }
    osl_unloadModule( aMod );
    return ret;
}

#else

#define get_desktop_environment() DESKTOP_NONE // For now...

#endif

static SalInstance* autodetect_plugin()
{
    static const char* pTDEFallbackList[] =
    {
        "tde", "kde4", "kde", "gtk3", "gtk", "gen", 0
    };

    static const char* pKDEFallbackList[] =
    {
        "kde4", "kde", "gtk3", "gtk", "gen", 0
    };

    static const char* pStandardFallbackList[] =
    {
        "gtk3", "gtk", "gen", 0
    };

    static const char* pHeadlessFallbackList[] =
    {
        "svp", 0
    };

    DesktopType desktop = get_desktop_environment();
    const char ** pList = pStandardFallbackList;
    int nListEntry = 0;

    // no server at all: dummy plugin
    if ( desktop == DESKTOP_NONE )
        pList = pHeadlessFallbackList;
    else if ( desktop == DESKTOP_GNOME )
        pList = pStandardFallbackList;
    else if( desktop == DESKTOP_TDE )
        pList = pTDEFallbackList;
    else if( desktop == DESKTOP_KDE )
    {
        pList = pKDEFallbackList;
        nListEntry = 1;
    }
    else if( desktop == DESKTOP_KDE4 )
        pList = pKDEFallbackList;

    SalInstance* pInst = NULL;
    while( pList[nListEntry] && pInst == NULL )
    {
        rtl::OUString aTry( rtl::OUString::createFromAscii( pList[nListEntry] ) );
        pInst = tryInstance( aTry );
        #if OSL_DEBUG_LEVEL > 1
        if( pInst )
            std::fprintf( stderr, "plugin autodetection: %s\n", pList[nListEntry] );
        #endif
        nListEntry++;
    }

    return pInst;
}

static SalInstance* check_headless_plugin()
{
    int nParams = osl_getCommandArgCount();
    OUString aParam;
    for( int i = 0; i < nParams; i++ )
    {
        osl_getCommandArg( i, &aParam.pData );
        if( aParam == "-headless" || aParam == "--headless" )
        {
            return tryInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "svp" ) ) );
        }
    }
    return NULL;
}

SalInstance *CreateSalInstance()
{
    SalInstance*    pInst = NULL;

    static const char* pUsePlugin = getenv( "SAL_USE_VCLPLUGIN" );

    pInst = check_headless_plugin();

    if( !pInst && pUsePlugin && *pUsePlugin )
        pInst = tryInstance( OUString::createFromAscii( pUsePlugin ), true );

    if( ! pInst )
        pInst = autodetect_plugin();

    // fallback, try everything
    const char* pPlugin[] = { "gtk3", "gtk", "kde4", "kde", "tde", "gen", 0 };

    for ( int i = 0; !pInst && pPlugin[ i ]; ++i )
        pInst = tryInstance( OUString::createFromAscii( pPlugin[ i ] ) );

    if( ! pInst )
    {
        std::fprintf( stderr, "no suitable windowing system found, exiting.\n" );
        _exit( 1 );
    }

    // acquire SolarMutex
    pInst->AcquireYieldMutex( 1 );

    return pInst;
}

void DestroySalInstance( SalInstance *pInst )
{
    // release SolarMutex
    pInst->ReleaseYieldMutex();

    delete pInst;
    if( pCloseModule )
        osl_unloadModule( pCloseModule );
}

void InitSalData()
{
}

void DeInitSalData()
{
}

void InitSalMain()
{
}

void DeInitSalMain()
{
}

void SalAbort( const rtl::OUString& rErrorText, bool bDumpCore )
{
    if( rErrorText.isEmpty() )
        std::fprintf( stderr, "Application Error\n" );
    else
        std::fprintf( stderr, "%s\n", rtl::OUStringToOString(rErrorText, osl_getThreadTextEncoding()).getStr() );
    if( bDumpCore )
        abort();
    else
        _exit(1);
}

static const char * desktop_strings[] = { "none", "unknown", "GNOME", "TDE", "KDE", "KDE4" };

const OUString& SalGetDesktopEnvironment()
{
    static rtl::OUString aRet;
    if( aRet.isEmpty())
    {
        rtl::OUStringBuffer buf( 8 );
        buf.appendAscii( desktop_strings[ get_desktop_environment() ] );
        aRet = buf.makeStringAndClear();
    }
    return aRet;
}

SalData::SalData() :
    m_pInstance(NULL),
    m_pPlugin(NULL),
    m_pPIManager(NULL)
{
}

SalData::~SalData()
{
    psp::PrinterInfoManager::release();
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>#pragma once

#include <agency/detail/config.hpp>
#include <agency/new_executor_traits.hpp>
#include <agency/detail/tuple.hpp>
#include <agency/detail/integer_sequence.hpp>
#include <agency/coordinate.hpp>
#include <utility>
#include <type_traits>

namespace agency
{
namespace detail
{
namespace new_executor_traits_detail
{

template<class T, class Executor>
using shared_parameter_container = typename new_executor_traits<Executor>::template container<T>;

template<class Executor, class T>
shared_parameter_container<T,Executor> make_shared_parameter_container(Executor&, size_t n, const T& shared_init)
{
  return shared_parameter_container<T,Executor>(n, shared_init);
}

template<size_t depth, class Shape>
__AGENCY_ANNOTATION
size_t number_of_groups_at_depth(const Shape& shape)
{
  // to compute the number of groups at a particular depth given a shape,
  // take the first depth elements of shape and return shape_size
  return detail::shape_size(detail::tuple_take<depth>(shape));
}

template<class Executor, class... Types>
using tuple_of_shared_parameter_containers = detail::tuple<shared_parameter_container<Types,Executor>...>;

template<class Executor, class... Types>
struct tuple_of_shared_parameter_containers_war_nvbug1665680
{
  using type = detail::tuple<shared_parameter_container<Types,Executor>...>;
};

template<size_t... Indices, class Executor, class... Types>
tuple_of_shared_parameter_containers<Executor,Types...>
  make_tuple_of_shared_parameter_containers(detail::index_sequence<Indices...>, Executor& ex, typename new_executor_traits<Executor>::shape_type shape, const Types&... shared_inits)
{
  return detail::make_tuple(make_shared_parameter_container(ex, number_of_groups_at_depth<Indices>(shape), shared_inits)...);
}

template<class Executor, class... Types>
tuple_of_shared_parameter_containers<Executor, typename std::decay<Types>::type...>
  make_tuple_of_shared_parameter_containers(Executor& ex, typename new_executor_traits<Executor>::shape_type shape, Types&&... shared_inits)
{
  return make_tuple_of_shared_parameter_containers(detail::make_index_sequence<sizeof...(shared_inits)>(), ex, shape, std::forward<Types>(shared_inits)...);
}

} // end new_executor_traits_detail
} // end detail
} // end agency

<commit_msg>Workaround nvbug 1665680<commit_after>#pragma once

#include <agency/detail/config.hpp>
#include <agency/new_executor_traits.hpp>
#include <agency/detail/tuple.hpp>
#include <agency/detail/integer_sequence.hpp>
#include <agency/coordinate.hpp>
#include <utility>
#include <type_traits>

namespace agency
{
namespace detail
{
namespace new_executor_traits_detail
{

template<class T, class Executor>
using shared_parameter_container = typename new_executor_traits<Executor>::template container<T>;

template<class Executor, class T>
shared_parameter_container<T,Executor> make_shared_parameter_container(Executor&, size_t n, const T& shared_init)
{
  return shared_parameter_container<T,Executor>(n, shared_init);
}

template<size_t depth, class Shape>
__AGENCY_ANNOTATION
size_t number_of_groups_at_depth(const Shape& shape)
{
  // to compute the number of groups at a particular depth given a shape,
  // take the first depth elements of shape and return shape_size
  return detail::shape_size(detail::tuple_take<depth>(shape));
}

template<class Executor, class... Types>
using tuple_of_shared_parameter_containers = detail::tuple<shared_parameter_container<Types,Executor>...>;

template<class Executor, class... Types>
struct tuple_of_shared_parameter_containers_war_nvbug1665680
{
  using type = detail::tuple<shared_parameter_container<Types,Executor>...>;
};

template<size_t... Indices, class Executor, class... Types>
//tuple_of_shared_parameter_containers<Executor,Types...>
typename tuple_of_shared_parameter_containers_war_nvbug1665680<Executor,Types...>::type
  make_tuple_of_shared_parameter_containers(detail::index_sequence<Indices...>, Executor& ex, typename new_executor_traits<Executor>::shape_type shape, const Types&... shared_inits)
{
  return detail::make_tuple(make_shared_parameter_container(ex, number_of_groups_at_depth<Indices>(shape), shared_inits)...);
}

template<class Executor, class... Types>
//tuple_of_shared_parameter_containers<Executor, typename std::decay<Types>::type...>
typename tuple_of_shared_parameter_containers_war_nvbug1665680<Executor,typename std::decay<Types>::type...>::type
  make_tuple_of_shared_parameter_containers(Executor& ex, typename new_executor_traits<Executor>::shape_type shape, Types&&... shared_inits)
{
  return make_tuple_of_shared_parameter_containers(detail::make_index_sequence<sizeof...(shared_inits)>(), ex, shape, std::forward<Types>(shared_inits)...);
}

} // end new_executor_traits_detail
} // end detail
} // end agency

<|endoftext|>


<commit_before>// Copyright since 2016 : Evgenii Shatunov (github.com/FrankStain/jnipp-test)
// Apache 2.0 License
#include <main.h>
#include <gtest/gtest.h>

#define DECLARE_TEST_ENV( NAME, RET, ... )																		\
	jnipp::ClassHandle class_handle{ "com/pfs/jnipptest/TestFunctionDerivedContainer" };						\
	jnipp::ClassHandle base_class_handle{ "com/pfs/jnipptest/TestFunctionContainer" };							\
																												\
	jnipp::FunctionHandle<RET, ##__VA_ARGS__>	func{ base_class_handle, NAME };								\
	jnipp::FieldHandle<bool>					call_check{ base_class_handle, "m_is_called" };					\
	jnipp::ObjectHandle							test_object{ jnipp::ObjectHandle::NewObject( class_handle ) };	\
																												\
	EXPECT_TRUE( func );																						\
	EXPECT_TRUE( call_check );																					\
	EXPECT_TRUE( test_object )

#define EXAMINE_CALL_FLAG( ... )										\
	{																	\
		bool is_called = false;											\
		EXPECT_TRUE( call_check.GetValue( test_object, is_called ) );	\
		EXPECT_TRUE( is_called );										\
	}

//TEST( TestFunctionHandle, CheckFunctionIds )
//{
//	jnipp::ClassHandle base_class{ "com/pfs/jnipptest/TestFunctionContainer" };
//	jnipp::ClassHandle derived_class{ "com/pfs/jnipptest/TestFunctionDerivedContainer" };
//
//	jnipp::FunctionHandle<void>	derived_class_func{ derived_class, "VoidNoArguments" };
//	jnipp::FunctionHandle<void>	base_class_func{ base_class, "VoidNoArguments" };
//
//	EXPECT_EQ( *base_class_func, *derived_class_func );
//};

TEST( TestFunctionHandle, CallNvVoidNoArguments )
{
	DECLARE_TEST_ENV( "VoidNoArguments", void );

	func.CallNonVirtual( test_object, class_handle );

	EXAMINE_CALL_FLAG();
};

TEST( TestFunctionHandle, CallNvVoidOneArgument )
{
	DECLARE_TEST_ENV( "VoidOneArgument", void, const char* );

	func.CallNonVirtual( test_object, class_handle, "1" );

	EXAMINE_CALL_FLAG();
};

TEST( TestFunctionHandle, CallNvVoidTwoArguments )
{
	DECLARE_TEST_ENV( "VoidTwoArguments", void, const char*, const char* );

	func.CallNonVirtual( test_object, class_handle, "1", "2" );

	EXAMINE_CALL_FLAG();
};

TEST( TestFunctionHandle, CallNvVoidThreeArguments )
{
	DECLARE_TEST_ENV( "VoidThreeArguments", void, const char*, const char*, const char* );

	func.CallNonVirtual( test_object, class_handle, "1", "2", "3" );

	EXAMINE_CALL_FLAG();
};

TEST( TestFunctionHandle, CallNvStringNoArguments )
{
	DECLARE_TEST_ENV( "StringNoArguments", std::string );

	auto ret = func.CallNonVirtual( test_object, class_handle );

	EXAMINE_CALL_FLAG();
	EXPECT_STREQ( "Jni++", ret.c_str() );
};

TEST( TestFunctionHandle, CallNvStringOneArgument )
{
	DECLARE_TEST_ENV( "StringOneArgument", std::string, const char* );

	auto ret = func.CallNonVirtual( test_object, class_handle, "1" );

	EXAMINE_CALL_FLAG();
	EXPECT_STREQ( "1", ret.c_str() );
};

TEST( TestFunctionHandle, CallNvStringTwoArguments )
{
	DECLARE_TEST_ENV( "StringTwoArguments", std::string, const char*, const char* );

	auto ret = func.CallNonVirtual( test_object, class_handle, "1", "2" );

	EXAMINE_CALL_FLAG();
	EXPECT_STREQ( "1 2", ret.c_str() );
};

TEST( TestFunctionHandle, CallNvStringThreeArguments )
{
	DECLARE_TEST_ENV( "StringThreeArguments", std::string, const char*, const char*, const char* );

	auto ret = func.CallNonVirtual( test_object, class_handle, "1", "2", "3" );

	EXAMINE_CALL_FLAG();
	EXPECT_STREQ( "1 2 3", ret.c_str() );
};
<commit_msg>Tests of non-virtual call refactored.<commit_after>// Copyright since 2016 : Evgenii Shatunov (github.com/FrankStain/jnipp-test)
// Apache 2.0 License
#include <main.h>
#include <gtest/gtest.h>

#define DECLARE_TEST_ENV( NAME, RET, ... )																		\
	jnipp::ClassHandle derived_class{ "com/pfs/jnipptest/TestFunctionDerivedContainer" };						\
	jnipp::ClassHandle basic_class{ derived_class.GetParentClassHandle() };										\
																												\
	jnipp::FunctionHandle<RET, ##__VA_ARGS__>	func{ basic_class, NAME };										\
	jnipp::FieldHandle<bool>					call_check{ basic_class, "m_is_called" };						\
	jnipp::ObjectHandle							test_object{ jnipp::ObjectHandle::NewObject( derived_class ) };	\
																												\
	EXPECT_TRUE( func );																						\
	EXPECT_TRUE( call_check );																					\
	EXPECT_TRUE( test_object )

#define EXAMINE_CALL_FLAG( ... )										\
	{																	\
		bool is_called = false;											\
		EXPECT_TRUE( call_check.GetValue( test_object, is_called ) );	\
		EXPECT_TRUE( is_called );										\
	}

//TEST( TestFunctionHandle, CheckFunctionIds )
//{
//	jnipp::ClassHandle base_class{ "com/pfs/jnipptest/TestFunctionContainer" };
//	jnipp::ClassHandle derived_class{ "com/pfs/jnipptest/TestFunctionDerivedContainer" };
//
//	jnipp::FunctionHandle<void>	derived_class_func{ derived_class, "VoidNoArguments" };
//	jnipp::FunctionHandle<void>	base_class_func{ base_class, "VoidNoArguments" };
//
//	EXPECT_EQ( *base_class_func, *derived_class_func );
//};

TEST( TestFunctionHandle, CallNvVoidNoArguments )
{
	DECLARE_TEST_ENV( "VoidNoArguments", void );

	func.CallNonVirtual( test_object );

	EXAMINE_CALL_FLAG();
};

TEST( TestFunctionHandle, CallNvVoidOneArgument )
{
	DECLARE_TEST_ENV( "VoidOneArgument", void, const char* );

	func.CallNonVirtual( test_object, "1" );

	EXAMINE_CALL_FLAG();
};

TEST( TestFunctionHandle, CallNvVoidTwoArguments )
{
	DECLARE_TEST_ENV( "VoidTwoArguments", void, const char*, const char* );

	func.CallNonVirtual( test_object, "1", "2" );

	EXAMINE_CALL_FLAG();
};

TEST( TestFunctionHandle, CallNvVoidThreeArguments )
{
	DECLARE_TEST_ENV( "VoidThreeArguments", void, const char*, const char*, const char* );

	func.CallNonVirtual( test_object, "1", "2", "3" );

	EXAMINE_CALL_FLAG();
};

TEST( TestFunctionHandle, CallNvStringNoArguments )
{
	DECLARE_TEST_ENV( "StringNoArguments", std::string );

	auto ret = func.CallNonVirtual( test_object );

	EXAMINE_CALL_FLAG();
	EXPECT_STREQ( "Jni++", ret.c_str() );
};

TEST( TestFunctionHandle, CallNvStringOneArgument )
{
	DECLARE_TEST_ENV( "StringOneArgument", std::string, const char* );

	auto ret = func.CallNonVirtual( test_object, "1" );

	EXAMINE_CALL_FLAG();
	EXPECT_STREQ( "1", ret.c_str() );
};

TEST( TestFunctionHandle, CallNvStringTwoArguments )
{
	DECLARE_TEST_ENV( "StringTwoArguments", std::string, const char*, const char* );

	auto ret = func.CallNonVirtual( test_object, "1", "2" );

	EXAMINE_CALL_FLAG();
	EXPECT_STREQ( "1 2", ret.c_str() );
};

TEST( TestFunctionHandle, CallNvStringThreeArguments )
{
	DECLARE_TEST_ENV( "StringThreeArguments", std::string, const char*, const char*, const char* );

	auto ret = func.CallNonVirtual( test_object, "1", "2", "3" );

	EXAMINE_CALL_FLAG();
	EXPECT_STREQ( "1 2 3", ret.c_str() );
};
<|endoftext|>


<commit_before>#pragma once

#include "integrators/explicit_embedded_runge_kutta_nyström_integrator.hpp"

#include <algorithm>
#include <cmath>
#include <ctime>
#include <vector>

#include "glog/logging.h"
#include "quantities/quantities.hpp"

namespace principia {

using quantities::Difference;
using quantities::Quotient;

namespace integrators {

template<typename Position>
void ExplicitEmbeddedRungeKuttaNyströmIntegrator::Solve(
    RightHandSideComputation<Position> compute_acceleration,
    SystemState<Position, Variation<Position>> const& initial_value,
    Time const& t_final,
    Time const& first_time_step,
    Difference<Position> const& position_tolerance,
    Variation<Position> const& velocity_tolerance,
    double const safety_factor,
    not_null<Solution<Position, Variation<Position>>*> const solution) const {
  int const dimension = initial_value.positions.size();
  CHECK_EQ(initial_value.momenta.size(), dimension);
  CHECK_NE(first_time_step, Time());
  bool const forward = first_time_step > Time();
  if (forward) {
    CHECK_LT(initial_value.time, t_final);
  } else {
    // Integrating backward.
    CHECK_GT(initial_value.time, t_final);
  }
  using Displacement = Difference<Position>;
  using Velocity = Variation<Position>;
  using Acceleration = Variation<Velocity>;
  // The timestep.
  Time h = first_time_step;
  DoublePrecision<Time> t;
  std::vector<Displacement> ∆q(dimension);
  std::vector<Velocity> ∆v(dimension);
  std::vector<DoublePrecision<Position>> q(dimension);
  std::vector<DoublePrecision<Position>> v(dimension);
  // The low-order integration is not performed using compensated summation.
  std::vector<Position> q_low_order(dimension);
  std::vector<Velocity> v_low_order(dimension);
  // TODO(egg): this is a rectangular container, use something more appropriate.
  std::vector<std::vector<Acceleration>> g(stages_);
  for (auto& g_stage : g) {
    g_stage.resize(dimension);
  }
  Time t_stage;
  std::vector<Displacement> q_stage(dimension);

  for (int k = 0; k < dimension; ++k) {
    ∆q[k] *= h;
  }
  for (int i = 0; i < stages_; ++i) {
    t_stage = t.value + c[i] * h;
    for (int k = 0; k < dimension; ++k) {
      for (int j = 0; j < i; ++j) {
        q_stage[k] += g[j][k] * a[i][j]
      }
      q_stage[k] *= h;
      q_stage[k] += c[i] * v[k].value;
      q_stage[k] *= h;
      q_stage[k] += q[k].value;
    }
    compute_acceleration(t_stage, q_stage, &g[i]);
  }
  for (int k = 0; k < dimension; ++k) {
    for (int i = 0; i < stages_; ++i) {
      ∆q[k] += b_hat_[i] * g[i][k];
    }
    ∆q[k] *= h;
    ∆q[k] += v[k].value;
    ∆q[k] *= h;
  }
}

}  // namespace integrators
}  // namespace principia
<commit_msg>some implementation<commit_after>#pragma once

#include "integrators/explicit_embedded_runge_kutta_nyström_integrator.hpp"

#include <algorithm>
#include <cmath>
#include <ctime>
#include <vector>

#include "glog/logging.h"
#include "quantities/quantities.hpp"

namespace principia {

using quantities::Difference;
using quantities::Quotient;

namespace integrators {

template<typename Position>
void ExplicitEmbeddedRungeKuttaNyströmIntegrator::Solve(
    RightHandSideComputation<Position> compute_acceleration,
    SystemState<Position, Variation<Position>> const& initial_value,
    Time const& t_final,
    Time const& first_time_step,
    Difference<Position> const& position_tolerance,
    Variation<Position> const& velocity_tolerance,
    double const safety_factor,
    not_null<Solution<Position, Variation<Position>>*> const solution) const {
  int const dimension = initial_value.positions.size();
  CHECK_EQ(initial_value.momenta.size(), dimension);
  CHECK_NE(first_time_step, Time());
  bool const forward = first_time_step > Time();
  if (forward) {
    CHECK_LT(initial_value.time, t_final);
  } else {
    // Integrating backward.
    CHECK_GT(initial_value.time, t_final);
  }
  using Displacement = Difference<Position>;
  using Velocity = Variation<Position>;
  using Acceleration = Variation<Velocity>;
  // The timestep.
  Time h = first_time_step;
  DoublePrecision<Time> t;
  std::vector<Displacement> ∆q(dimension);
  std::vector<Velocity> ∆v(dimension);
  std::vector<DoublePrecision<Position>> q(dimension);
  std::vector<DoublePrecision<Position>> v(dimension);
  std::vector<Position> ∆q_low_order(dimension);
  std::vector<Velocity> ∆v_low_order(dimension);
  // TODO(egg): this is a rectangular container, use something more appropriate.
  std::vector<std::vector<Acceleration>> g(stages_);
  for (auto& g_stage : g) {
    g_stage.resize(dimension);
  }
  Time t_stage;
  std::vector<Position> q_stage(dimension);

  std::fill(∆q.begin(), ∆q.end(), Displacement());

  for (int i = 0; i < stages_; ++i) {
    t_stage = t.value + c[i] * h;
    for (int k = 0; k < dimension; ++k) {
      Acceleration ∑_a_ij_g_j;
      for (int j = 0; j < i; ++j) {
        ∑_a_ij_g_j += g[j][k] * a[i][j]
      }
      q_stage[k] = q[k].value + h * (c[i] * v[k].value + h * ∑_a_ij_g_j);
    }
    compute_acceleration(t_stage, q_stage, &g[i]);
  }

  for (int k = 0; k < dimension; ++k) {
    Acceleration ∑_b_hat_i_g_i;
    Acceleration ∑_b_i_g_i;
    Acceleration ∑_b_prime_hat_i_g_i;
    Acceleration ∑_b_prime_i_g_i;
    // TODO(egg): this would be more readable if it were aligned on the += / =.
    for (int i = 0; i < stages_; ++i) {
      ∑_b_hat_i_g_i += b_hat_[i] * g[i][k];
      ∑_b_i_g_i += b_[i] * g[i][k];
      ∑_b_prime_hat_i_g_i += b_prime_hat_[i] * g[i][k];
      ∑_b_prime_i_g_i += b_prime_[i] * g[i][k];
    }
    ∆q[k] = h * (h * (∑_b_hat_i_g_i) + v[k].value);
    ∆q_low_order[k] = h * (h * (∑_b_i_g_i) + v[k].value);
    ∆v[k] = h * ∑_b_prime_hat_i_g_i;
    ∆v_low_order[k] = h * ∑_b_prime_i_g_i;
  }
}

}  // namespace integrators
}  // namespace principia
<|endoftext|>


<commit_before>/**
 * \file get-set-blob.cpp
 * \author Denis Martinez
 * \date 2009-09-06
 */

#include <ppasskeeper.h>
#include "unittest.h"

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>

ppk_entry* app_entry, * net_entry, * item_entry;
ppk_data* data;
std::vector<ppk_entry*> entries;

void delete_all()
{
	delete app_entry;
	delete net_entry;
	delete item_entry;
	delete data;
}

std::string readFile(std::string filepath)
{
	//open the file
	std::ifstream inputfile(filepath.c_str());
	if(inputfile.is_open())
	{
		//Read the password from the file
		std::ostringstream pwd_s;
		pwd_s << inputfile.rdbuf();

		//close the file
		inputfile.close();

		return pwd_s.str();
	}
	else
		return std::string();
}

void run(int argc, char** argv)
{
	char *module_id = argv[1];

	app_entry=ppk_application_entry_new("test","utstblob_write_string");
	net_entry=ppk_network_entry_new(NULL, "test", "utstblob_write_string", 99);
	item_entry=ppk_item_entry_new("utstblob_write_string");
	entries.push_back(app_entry);
	entries.push_back(net_entry);
	entries.push_back(item_entry);

	FAILIF(ppk_is_locked()==PPK_TRUE);
	FAILIF(ppk_module_is_available(module_id)==PPK_FALSE);

	size_t max_size=ppk_module_max_data_size(module_id, ppk_blob);
	if(max_size==0)
	{
		std::cerr << "* No blob support in " << module_id << std::endl;
		delete_all();
		return;
	}

	//If the module doesn't support writing/listing
	ppk_boolean writable=ppk_module_is_writable(module_id);
	if(writable==PPK_FALSE)
	{
		std::cerr << "* The module " << module_id << " is read-only" << std::endl;
	}

	std::string file=readFile(argv[0]);
	bool read_file_ok = file != std::string();
	FAILIF(! read_file_ok);

	if (max_size<file.size())
		file=file.substr(0, max_size);

	data=ppk_blob_data_new(file.data(), file.size());

	for (int i = 0; i < entries.size(); ++i)
	{
		ppk_entry* entry = entries[i];

		/* Write */
		printf("Set entry !\n");
		ppk_error res=ppk_module_set_entry(module_id, entry, data, ppk_wf_none);
		ASSERT(writable == PPK_TRUE && res == PPK_OK);
		if(res == PPK_OK)
		{
			/* Read */
			printf("read\n");
			ppk_data* edata;
			res=ppk_module_get_entry(module_id, entry, &edata, ppk_rf_none);
			ASSERT(res == PPK_OK);
			if (res != PPK_OK)
				continue;

			/* Delete */
			printf("delete\n");
			res=ppk_module_remove_entry(module_id, entry, ppk_rf_none);
			ASSERT(writable == PPK_TRUE && res == PPK_OK);

			printf("Test la correspondance\n");
			bool valid_type = edata->type == ppk_blob;
			ASSERT(valid_type);
			if (valid_type)
			{
				std::string res;
				res.assign((const char*)edata->blob.data, edata->blob.size);
				ppk_data_free(edata);

				bool same_data = res == file;
				ASSERT(same_data);
				if(! same_data)
				{
					std::cerr << "* Before : size = " << file.size() << " and data = " << (const char*)file.data() << std::endl;
					std::cerr << "* After  : size = " << edata->blob.size << " and data = " << (const char*)edata->blob.data << std::endl;
				}
			}
		}
	}
	delete_all();
}
<commit_msg>Unittest: Get rid of some printf<commit_after>/**
 * \file get-set-blob.cpp
 * \author Denis Martinez
 * \date 2009-09-06
 */

#include <ppasskeeper.h>
#include "unittest.h"

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>

ppk_entry* app_entry, * net_entry, * item_entry;
ppk_data* data;
std::vector<ppk_entry*> entries;

void delete_all()
{
	delete app_entry;
	delete net_entry;
	delete item_entry;
	delete data;
}

std::string readFile(std::string filepath)
{
	//open the file
	std::ifstream inputfile(filepath.c_str());
	if(inputfile.is_open())
	{
		//Read the password from the file
		std::ostringstream pwd_s;
		pwd_s << inputfile.rdbuf();

		//close the file
		inputfile.close();

		return pwd_s.str();
	}
	else
		return std::string();
}

void run(int argc, char** argv)
{
	char *module_id = argv[1];

	app_entry=ppk_application_entry_new("test","utstblob_write_string");
	net_entry=ppk_network_entry_new(NULL, "test", "utstblob_write_string", 99);
	item_entry=ppk_item_entry_new("utstblob_write_string");
	entries.push_back(app_entry);
	entries.push_back(net_entry);
	entries.push_back(item_entry);

	FAILIF(ppk_is_locked()==PPK_TRUE);
	FAILIF(ppk_module_is_available(module_id)==PPK_FALSE);

	size_t max_size=ppk_module_max_data_size(module_id, ppk_blob);
	if(max_size==0)
	{
		std::cerr << "* No blob support in " << module_id << std::endl;
		delete_all();
		return;
	}

	//If the module doesn't support writing/listing
	ppk_boolean writable=ppk_module_is_writable(module_id);
	if(writable==PPK_FALSE)
	{
		std::cerr << "* The module " << module_id << " is read-only" << std::endl;
	}

	std::string file=readFile(argv[0]);
	bool read_file_ok = file != std::string();
	FAILIF(! read_file_ok);

	if (max_size<file.size())
		file=file.substr(0, max_size);

	data=ppk_blob_data_new(file.data(), file.size());

	for (int i = 0; i < entries.size(); ++i)
	{
		ppk_entry* entry = entries[i];

		/* Write */
		ppk_error res=ppk_module_set_entry(module_id, entry, data, ppk_wf_none);
		ASSERT(writable == PPK_TRUE && res == PPK_OK);
		if(res == PPK_OK)
		{
			/* Read */
			ppk_data* edata;
			res=ppk_module_get_entry(module_id, entry, &edata, ppk_rf_none);
			ASSERT(res == PPK_OK);
			if (res != PPK_OK)
				continue;

			/* Delete */
			res=ppk_module_remove_entry(module_id, entry, ppk_rf_none);
			ASSERT(writable == PPK_TRUE && res == PPK_OK);

			bool valid_type = edata->type == ppk_blob;
			ASSERT(valid_type);
			if (valid_type)
			{
				std::string res;
				res.assign((const char*)edata->blob.data, edata->blob.size);
				ppk_data_free(edata);

				bool same_data = res == file;
				ASSERT(same_data);
				if(! same_data)
				{
					std::cerr << "* Before : size = " << file.size() << " and data = " << (const char*)file.data() << std::endl;
					std::cerr << "* After  : size = " << edata->blob.size << " and data = " << (const char*)edata->blob.data << std::endl;
				}
			}
		}
	}
	delete_all();
}
<|endoftext|>


<commit_before>#include <vector>
#include <unordered_set>

#include "taichi/ir/ir.h"
#include "taichi/ir/analysis.h"
#include "taichi/ir/visitors.h"
#include "taichi/ir/transforms.h"

TLANG_NAMESPACE_BEGIN

class IRVerifier : public BasicStmtVisitor {
 private:
  Block *current_block;
  // each scope corresponds to an unordered_set
  std::vector<std::unordered_set<Stmt *>> visible_stmts;

 public:
  using BasicStmtVisitor::visit;

  explicit IRVerifier(IRNode *root) : current_block(nullptr) {
    allow_undefined_visitor = true;
    invoke_default_visitor = true;
    if (!root->is<Block>()) {
      visible_stmts.emplace_back();
      current_block = root->as<Stmt>()->parent;
    } else
      current_block = nullptr;
  }

  void basic_verify(Stmt *stmt) {
    TI_ASSERT_INFO(stmt->parent == current_block,
                   "stmt({})->parent({}) != current_block({})", stmt->id,
                   fmt::ptr(stmt->parent), fmt::ptr(current_block));
    for (auto &op : stmt->get_operands()) {
      if (op == nullptr)
        continue;
      bool found = false;
      for (int depth = (int)visible_stmts.size() - 1; depth >= 0; depth--) {
        if (visible_stmts[depth].find(op) != visible_stmts[depth].end()) {
          found = true;
          break;
        }
      }
      TI_ASSERT_INFO(
          found,
          "IR broken: stmt {} cannot have operand {}."
          " If you are using autodiff, please check"
          " https://taichi.readthedocs.io/en/stable/"
          "differentiable_programming.html#kernel-simplicity-rule."
          " If it doesn't help, please report this bug by opening an issue at"
          " https://github.com/taichi-dev/taichi to help us improve."
          " Thanks in advance!",
          stmt->id, op->id);
    }
    visible_stmts.back().insert(stmt);
  }

  void preprocess_container_stmt(Stmt *stmt) override {
    basic_verify(stmt);
  }

  void visit(Stmt *stmt) override {
    basic_verify(stmt);
  }

  void visit(Block *block) override {
    TI_ASSERT(block->parent == current_block);
    auto backup_block = current_block;
    current_block = block;
    visible_stmts.emplace_back();
    for (auto &stmt : block->statements) {
      stmt->accept(this);
    }
    current_block = backup_block;
    visible_stmts.pop_back();
  }

  void visit(LocalLoadStmt *stmt) override {
    basic_verify(stmt);
    for (int i = 0; i < stmt->width(); i++) {
      TI_ASSERT(stmt->ptr[i].var->is<AllocaStmt>());
    }
  }

  void visit(LocalStoreStmt *stmt) override {
    basic_verify(stmt);
    TI_ASSERT(stmt->ptr->is<AllocaStmt>());
  }

  void visit(LoopIndexStmt *stmt) override {
    basic_verify(stmt);
    TI_ASSERT(stmt->loop);
    if (stmt->loop->is<OffloadedStmt>()) {
      TI_ASSERT(stmt->loop->as<OffloadedStmt>()->task_type ==
                    OffloadedStmt::TaskType::struct_for ||
                stmt->loop->as<OffloadedStmt>()->task_type ==
                    OffloadedStmt::TaskType::range_for);
    } else {
      TI_ASSERT(stmt->loop->is<StructForStmt>() ||
                stmt->loop->is<RangeForStmt>());
    }
  }

  static void run(IRNode *root) {
    IRVerifier verifier(root);
    root->accept(&verifier);
  }
};

namespace irpass::analysis {
void verify(IRNode *root) {
  TI_AUTO_PROF;
  if (!root->is<Block>()) {
    TI_WARN("IR root is not a Block. Skipping verification.");
    // TODO: support this case
  } else {
    IRVerifier::run(root);
  }
}
}  // namespace irpass::analysis

TLANG_NAMESPACE_END
<commit_msg>[ir] Restore verification for OffloadedStmt (#1790)<commit_after>#include <vector>
#include <unordered_set>

#include "taichi/ir/ir.h"
#include "taichi/ir/analysis.h"
#include "taichi/ir/visitors.h"
#include "taichi/ir/transforms.h"

TLANG_NAMESPACE_BEGIN

class IRVerifier : public BasicStmtVisitor {
 private:
  Block *current_block;
  // each scope corresponds to an unordered_set
  std::vector<std::unordered_set<Stmt *>> visible_stmts;

 public:
  using BasicStmtVisitor::visit;

  explicit IRVerifier(IRNode *root) : current_block(nullptr) {
    allow_undefined_visitor = true;
    invoke_default_visitor = true;
    if (!root->is<Block>()) {
      visible_stmts.emplace_back();
      current_block = nullptr;
    } else
      current_block = nullptr;
  }

  void basic_verify(Stmt *stmt) {
    if (current_block != nullptr) {
      // Temporary fix for root being OffloadedStmt
      TI_ASSERT_INFO(stmt->parent == current_block,
                     "stmt({})->parent({}) != current_block({})", stmt->id,
                     fmt::ptr(stmt->parent), fmt::ptr(current_block));
    }
    for (auto &op : stmt->get_operands()) {
      if (op == nullptr)
        continue;
      bool found = false;
      for (int depth = (int)visible_stmts.size() - 1; depth >= 0; depth--) {
        if (visible_stmts[depth].find(op) != visible_stmts[depth].end()) {
          found = true;
          break;
        }
      }
      TI_ASSERT_INFO(
          found,
          "IR broken: stmt {} cannot have operand {}."
          " If you are using autodiff, please check"
          " https://taichi.readthedocs.io/en/stable/"
          "differentiable_programming.html#kernel-simplicity-rule."
          " If it doesn't help, please report this bug by opening an issue at"
          " https://github.com/taichi-dev/taichi to help us improve."
          " Thanks in advance!",
          stmt->id, op->id);
    }
    visible_stmts.back().insert(stmt);
  }

  void preprocess_container_stmt(Stmt *stmt) override {
    basic_verify(stmt);
  }

  void visit(Stmt *stmt) override {
    basic_verify(stmt);
  }

  void visit(Block *block) override {
    TI_ASSERT(block->parent == current_block);
    auto backup_block = current_block;
    current_block = block;
    visible_stmts.emplace_back();
    for (auto &stmt : block->statements) {
      stmt->accept(this);
    }
    current_block = backup_block;
    visible_stmts.pop_back();
  }

  void visit(LocalLoadStmt *stmt) override {
    basic_verify(stmt);
    for (int i = 0; i < stmt->width(); i++) {
      TI_ASSERT(stmt->ptr[i].var->is<AllocaStmt>());
    }
  }

  void visit(LocalStoreStmt *stmt) override {
    basic_verify(stmt);
    TI_ASSERT(stmt->ptr->is<AllocaStmt>());
  }

  void visit(LoopIndexStmt *stmt) override {
    basic_verify(stmt);
    TI_ASSERT(stmt->loop);
    if (stmt->loop->is<OffloadedStmt>()) {
      TI_ASSERT(stmt->loop->as<OffloadedStmt>()->task_type ==
                    OffloadedStmt::TaskType::struct_for ||
                stmt->loop->as<OffloadedStmt>()->task_type ==
                    OffloadedStmt::TaskType::range_for);
    } else {
      TI_ASSERT(stmt->loop->is<StructForStmt>() ||
                stmt->loop->is<RangeForStmt>());
    }
  }

  static void run(IRNode *root) {
    IRVerifier verifier(root);
    root->accept(&verifier);
  }
};

namespace irpass::analysis {
void verify(IRNode *root) {
  TI_AUTO_PROF;
  if (!root->is<Block>() && !root->is<OffloadedStmt>()) {
    TI_WARN(
        "IR root is neither a Block nor an OffloadedStmt."
        " Skipping verification.");
  } else {
    IRVerifier::run(root);
  }
}
}  // namespace irpass::analysis

TLANG_NAMESPACE_END
<|endoftext|>


<commit_before>// Copyright (c) 2021 ASMlover. All rights reserved.
//
//  ______             __                  ___
// /\__  _\           /\ \                /\_ \
// \/_/\ \/    __     \_\ \  _____     ___\//\ \      __
//    \ \ \  /'__`\   /'_` \/\ '__`\  / __`\\ \ \   /'__`\
//     \ \ \/\ \L\.\_/\ \L\ \ \ \L\ \/\ \L\ \\_\ \_/\  __/
//      \ \_\ \__/.\_\ \___,_\ \ ,__/\ \____//\____\ \____\
//       \/_/\/__/\/_/\/__,_ /\ \ \/  \/___/ \/____/\/____/
//                             \ \_\
//                              \/_/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include "common.hh"
#include "harness.hh"

int main(int argc, char* argv[]) {
  TADPOLE_UNUSED(argc), TADPOLE_UNUSED(argv);

#if defined(_TADPOLE_RUN_HARNESS)
  tadpole::harness::run_all_harness();
#endif

  return 0;
}
<commit_msg>:construction: chore(eval): add eval for tadpole interpreter<commit_after>// Copyright (c) 2021 ASMlover. All rights reserved.
//
//  ______             __                  ___
// /\__  _\           /\ \                /\_ \
// \/_/\ \/    __     \_\ \  _____     ___\//\ \      __
//    \ \ \  /'__`\   /'_` \/\ '__`\  / __`\\ \ \   /'__`\
//     \ \ \/\ \L\.\_/\ \L\ \ \ \L\ \/\ \L\ \\_\ \_/\  __/
//      \ \_\ \__/.\_\ \___,_\ \ ,__/\ \____//\____\ \____\
//       \/_/\/__/\/_/\/__,_ /\ \ \/  \/___/ \/____/\/____/
//                             \ \_\
//                              \/_/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include "common.hh"
#include "colorful.hh"
#include "harness.hh"
#include "vm.hh"

namespace tp = tadpole;

static int eval(tp::TadpoleVM& vm, const tp::str_t& source_bytes) {
  tp::InterpretRet r = vm.interpret(source_bytes);
  if (r == tp::InterpretRet::ERUNTIME)
    return -1;
  else if (r == tp::InterpretRet::ECOMPILE)
    return -2;
  return 0;
}

int main(int argc, char* argv[]) {
  TADPOLE_UNUSED(argc), TADPOLE_UNUSED(argv);

#if defined(_TADPOLE_RUN_HARNESS)
  tp::harness::run_all_harness();
#endif

  return 0;
}
<|endoftext|>