<commit_before>#pragma once

#include <vector>
#include <list>
#include <memory>
#include <boost/asio.hpp>
#include <boost/timer.hpp>
#include "base/header.hpp"
#include "base/atimer.hpp"
#include "base/scope_guard.hpp"
#include "base/logger.hpp"
#include "base/async_send_queue.hpp"

using namespace czrpc::base;

namespace czrpc
{
namespace server
{
class connection;
using connection_ptr = std::shared_ptr<connection>;
using connection_weak_ptr = std::weak_ptr<connection>;
using router_callback = std::function<bool(const request_content&, const client_flag&, const std::shared_ptr<connection>&)>;
using handle_error_callback = std::function<void(const connection_ptr&)>;

class connection : public std::enable_shared_from_this<connection>
{
public:
    connection() = default;
    connection(const connection&) = delete;
    connection& operator=(const connection&) = delete;
    connection(boost::asio::io_service& ios,
               std::size_t timeout_milli, const router_callback& route_func,
               const handle_error_callback& handle_error_func)
        : ios_(ios), socket_(ios), timeout_milli_(timeout_milli), route_(route_func),
        handle_error_(handle_error_func) {}

    ~connection()
    {
        disconnect();
    }

    void start()
    {
        set_no_delay();
        read_head();
    }

    boost::asio::ip::tcp::socket& socket()
    {
        return socket_;
    }

#if 0
    void write(const std::string& body, const std::string& call_id = "")
    {
        unsigned int call_id_len = static_cast<unsigned int>(call_id.size());
        unsigned int body_len = static_cast<unsigned int>(body.size());
        if (call_id_len + body_len > max_buffer_len)
        {
            handle_error();
            throw std::runtime_error("Send data is too big");
        }

        std::string buffer = get_buffer(response_header{ call_id_len, body_len }, call_id, body);
        write_impl(buffer);
    }
#endif

    void write(const std::string& protocol, const std::string& body, serialize_mode mode)
    {
        unsigned int protocol_len = static_cast<unsigned int>(protocol.size());
        unsigned int body_len = static_cast<unsigned int>(body.size());
        if (protocol_len + body_len > max_buffer_len)
        {
            handle_error();
            throw std::runtime_error("Send data is too big");
        }

        std::string buffer = get_buffer(push_header{ protocol_len,  body_len, mode }, protocol, body);
        write_impl(buffer);
    }

    void async_write(const response_content& content)
    {
        unsigned int call_id_len = static_cast<unsigned int>(content.call_id.size());
        unsigned int message_name_len = static_cast<unsigned int>(content.message_name.size());
        unsigned int body_len = static_cast<unsigned int>(content.body.size());
        if (call_id_len + message_name_len + body_len > max_buffer_len)
        {
            handle_error();
            throw std::runtime_error("Send data is too big");
        }

        response_header header{ call_id_len, message_name_len, body_len };
        std::string buffer = get_buffer(response_data{ header, content });
        async_write_impl(buffer);
    }

    void async_write(const std::string& protocol, const std::string& body, serialize_mode mode)
    {
        unsigned int protocol_len = static_cast<unsigned int>(protocol.size());
        unsigned int body_len = static_cast<unsigned int>(body.size());
        if (protocol_len + body_len > max_buffer_len)
        {
            handle_error();
            throw std::runtime_error("Send data is too big");
        }

        std::string buffer = get_buffer(push_header{ protocol_len,  body_len, mode }, protocol, body);
        async_write_impl(buffer);
    }

    void disconnect()
    {
        if (socket_.is_open())
        {
            boost::system::error_code ignore_ec;
            socket_.shutdown(boost::asio::socket_base::shutdown_both, ignore_ec);
            socket_.close(ignore_ec);
        }
    }

private:
    void read_head()
    {
        auto self(this->shared_from_this());
        boost::asio::async_read(socket_, boost::asio::buffer(req_head_buf_),
                                [this, self](boost::system::error_code ec, std::size_t)
        {
            auto guard = make_guard([this, self]{ handle_error(); });
            if (!socket_.is_open())
            {
                log_warn("Socket is not open");
                return;
            }

            if (ec)
            {
                log_warn(ec.message());
                return;
            }

            if (check_head())
            {
                read_content();
                guard.dismiss();
            }
        });
    }

    bool check_head()
    {
        memcpy(&req_head_, req_head_buf_, sizeof(req_head_buf_));
        unsigned int len = req_head_.call_id_len + req_head_.protocol_len + req_head_.message_name_len  + req_head_.body_len;
        return (len > 0 && len < max_buffer_len) ? true : false;
    }

    void read_content()
    {
        content_.clear();
        content_.resize(req_head_.call_id_len + req_head_.protocol_len + req_head_.message_name_len + req_head_.body_len);
        auto self(this->shared_from_this());
        boost::asio::async_read(socket_, boost::asio::buffer(content_),
                                [this, self](boost::system::error_code ec, std::size_t)
        {
            read_head();
            auto guard = make_guard([this, self]{ handle_error(); });
            if (!socket_.is_open())
            {
                log_warn("Socket is not open");
                return;
            }

            if (ec)
            {
                log_warn(ec.message());
                return;
            }

            request_content content;
            content.call_id.assign(&content_[0], req_head_.call_id_len);
            content.protocol.assign(&content_[req_head_.call_id_len], req_head_.protocol_len);
            content.message_name.assign(&content_[req_head_.call_id_len + req_head_.protocol_len], req_head_.message_name_len);
            content.body.assign(&content_[req_head_.call_id_len + req_head_.protocol_len + req_head_.message_name_len],
                                req_head_.body_len);
            bool ok = route_(content, req_head_.flag, self);
            if (!ok)
            {
                log_warn("Router failed");
                return;
            }
            guard.dismiss();
        });
    }

    void set_no_delay()
    {
        boost::asio::ip::tcp::no_delay option(true);
        boost::system::error_code ec;
        socket_.set_option(option, ec);
    }

    std::string get_buffer(const response_data& data)
    {
        std::string buffer;
        buffer.append(reinterpret_cast<const char*>(&data.header), sizeof(data.header));
        buffer.append(data.content.call_id);
        buffer.append(data.content.message_name);
        buffer.append(data.content.body);
        return std::move(buffer);
    }

    std::string get_buffer(const push_header& head, const std::string& protocol, const std::string& body)
    {
        std::string buffer;
        buffer.append(reinterpret_cast<const char*>(&head), sizeof(head));
        buffer.append(protocol);
        buffer.append(body);
        return std::move(buffer);
    }

    void write_impl(const std::string& buffer)
    {
        boost::system::error_code ec;
        boost::asio::write(socket_, boost::asio::buffer(buffer), ec);
        if (ec)
        {
            handle_error();
            throw std::runtime_error(ec.message());
        }
    }

    void async_write_impl(const std::string& buffer)
    {
        auto self(this->shared_from_this());
        ios_.post([this, self, buffer]
        {
            std::cout << "size: " << send_queue_.size() << std::endl;
            bool is_empty = send_queue_.empty();
            send_queue_.emplace_back(buffer);
            if (is_empty)
            {
                async_write_impl();
            }
        });
    }

    void async_write_impl()
    {
        auto self(this->shared_from_this());
        boost::asio::async_write(socket_, boost::asio::buffer(send_queue_.front()),
                                 [this, self](boost::system::error_code ec, std::size_t)
        {
            if (!ec)
            {
                send_queue_.pop_front();
                if (!send_queue_.empty())
                {
                    async_write_impl();
                }
            }
            else
            {
                log_warn(ec.message());
                send_queue_.clear();
                handle_error();
            }
        });
    }

    void handle_error()
    {
        if (req_head_.flag.type == client_type::sub_client)
        {
            handle_error_(this->shared_from_this());
        }
    }

private:
    boost::asio::io_service& ios_;
    boost::asio::ip::tcp::socket socket_;
    char req_head_buf_[request_header_len];
    request_header req_head_;
    std::vector<char> content_;
    std::size_t timeout_milli_ = 0;
    router_callback route_;
    handle_error_callback handle_error_;
    async_send_queue send_queue_;
};

}
}

<commit_msg>update<commit_after>#pragma once

#include <vector>
#include <list>
#include <memory>
#include <boost/asio.hpp>
#include <boost/timer.hpp>
#include "base/header.hpp"
#include "base/atimer.hpp"
#include "base/scope_guard.hpp"
#include "base/logger.hpp"
#include "base/async_send_queue.hpp"

using namespace czrpc::base;

namespace czrpc
{
namespace server
{
class connection;
using connection_ptr = std::shared_ptr<connection>;
using connection_weak_ptr = std::weak_ptr<connection>;
using router_callback = std::function<bool(const request_content&, const client_flag&, const std::shared_ptr<connection>&)>;
using handle_error_callback = std::function<void(const connection_ptr&)>;

class connection : public std::enable_shared_from_this<connection>
{
public:
    connection() = default;
    connection(const connection&) = delete;
    connection& operator=(const connection&) = delete;
    connection(boost::asio::io_service& ios,
               std::size_t timeout_milli, const router_callback& route_func,
               const handle_error_callback& handle_error_func)
        : ios_(ios), socket_(ios), timeout_milli_(timeout_milli), route_(route_func),
        handle_error_(handle_error_func) {}

    ~connection()
    {
        disconnect();
    }

    void start()
    {
        set_no_delay();
        read_head();
    }

    boost::asio::ip::tcp::socket& socket()
    {
        return socket_;
    }

    void write(const response_content& content)
    {
        unsigned int call_id_len = static_cast<unsigned int>(content.call_id.size());
        unsigned int message_name_len = static_cast<unsigned int>(content.message_name.size());
        unsigned int body_len = static_cast<unsigned int>(content.body.size());
        if (call_id_len + message_name_len + body_len > max_buffer_len)
        {
            handle_error();
            throw std::runtime_error("Send data is too big");
        }

        response_header header{ call_id_len, message_name_len, body_len };
        std::string buffer = get_buffer(response_data{ header, content });
        write_impl(buffer);
    }

    void write(const std::string& protocol, const std::string& body, serialize_mode mode)
    {
        unsigned int protocol_len = static_cast<unsigned int>(protocol.size());
        unsigned int body_len = static_cast<unsigned int>(body.size());
        if (protocol_len + body_len > max_buffer_len)
        {
            handle_error();
            throw std::runtime_error("Send data is too big");
        }

        std::string buffer = get_buffer(push_header{ protocol_len,  body_len, mode }, protocol, body);
        write_impl(buffer);
    }

    void async_write(const response_content& content)
    {
        unsigned int call_id_len = static_cast<unsigned int>(content.call_id.size());
        unsigned int message_name_len = static_cast<unsigned int>(content.message_name.size());
        unsigned int body_len = static_cast<unsigned int>(content.body.size());
        if (call_id_len + message_name_len + body_len > max_buffer_len)
        {
            handle_error();
            throw std::runtime_error("Send data is too big");
        }

        response_header header{ call_id_len, message_name_len, body_len };
        std::string buffer = get_buffer(response_data{ header, content });
        async_write_impl(buffer);
    }

    void async_write(const std::string& protocol, const std::string& body, serialize_mode mode)
    {
        unsigned int protocol_len = static_cast<unsigned int>(protocol.size());
        unsigned int body_len = static_cast<unsigned int>(body.size());
        if (protocol_len + body_len > max_buffer_len)
        {
            handle_error();
            throw std::runtime_error("Send data is too big");
        }

        std::string buffer = get_buffer(push_header{ protocol_len,  body_len, mode }, protocol, body);
        async_write_impl(buffer);
    }

    void disconnect()
    {
        if (socket_.is_open())
        {
            boost::system::error_code ignore_ec;
            socket_.shutdown(boost::asio::socket_base::shutdown_both, ignore_ec);
            socket_.close(ignore_ec);
        }
    }

private:
    void read_head()
    {
        auto self(this->shared_from_this());
        boost::asio::async_read(socket_, boost::asio::buffer(req_head_buf_),
                                [this, self](boost::system::error_code ec, std::size_t)
        {
            auto guard = make_guard([this, self]{ handle_error(); });
            if (!socket_.is_open())
            {
                log_warn("Socket is not open");
                return;
            }

            if (ec)
            {
                log_warn(ec.message());
                return;
            }

            if (check_head())
            {
                read_content();
                guard.dismiss();
            }
        });
    }

    bool check_head()
    {
        memcpy(&req_head_, req_head_buf_, sizeof(req_head_buf_));
        unsigned int len = req_head_.call_id_len + req_head_.protocol_len + req_head_.message_name_len  + req_head_.body_len;
        return (len > 0 && len < max_buffer_len) ? true : false;
    }

    void read_content()
    {
        content_.clear();
        content_.resize(req_head_.call_id_len + req_head_.protocol_len + req_head_.message_name_len + req_head_.body_len);
        auto self(this->shared_from_this());
        boost::asio::async_read(socket_, boost::asio::buffer(content_),
                                [this, self](boost::system::error_code ec, std::size_t)
        {
            read_head();
            auto guard = make_guard([this, self]{ handle_error(); });
            if (!socket_.is_open())
            {
                log_warn("Socket is not open");
                return;
            }

            if (ec)
            {
                log_warn(ec.message());
                return;
            }

            request_content content;
            content.call_id.assign(&content_[0], req_head_.call_id_len);
            content.protocol.assign(&content_[req_head_.call_id_len], req_head_.protocol_len);
            content.message_name.assign(&content_[req_head_.call_id_len + req_head_.protocol_len], req_head_.message_name_len);
            content.body.assign(&content_[req_head_.call_id_len + req_head_.protocol_len + req_head_.message_name_len],
                                req_head_.body_len);
            bool ok = route_(content, req_head_.flag, self);
            if (!ok)
            {
                log_warn("Router failed");
                return;
            }
            guard.dismiss();
        });
    }

    void set_no_delay()
    {
        boost::asio::ip::tcp::no_delay option(true);
        boost::system::error_code ec;
        socket_.set_option(option, ec);
    }

    std::string get_buffer(const response_data& data)
    {
        std::string buffer;
        buffer.append(reinterpret_cast<const char*>(&data.header), sizeof(data.header));
        buffer.append(data.content.call_id);
        buffer.append(data.content.message_name);
        buffer.append(data.content.body);
        return std::move(buffer);
    }

    std::string get_buffer(const push_header& head, const std::string& protocol, const std::string& body)
    {
        std::string buffer;
        buffer.append(reinterpret_cast<const char*>(&head), sizeof(head));
        buffer.append(protocol);
        buffer.append(body);
        return std::move(buffer);
    }

    void write_impl(const std::string& buffer)
    {
        boost::system::error_code ec;
        boost::asio::write(socket_, boost::asio::buffer(buffer), ec);
        if (ec)
        {
            handle_error();
            throw std::runtime_error(ec.message());
        }
    }

    void async_write_impl(const std::string& buffer)
    {
        auto self(this->shared_from_this());
        ios_.post([this, self, buffer]
        {
            std::cout << "size: " << send_queue_.size() << std::endl;
            bool is_empty = send_queue_.empty();
            send_queue_.emplace_back(buffer);
            if (is_empty)
            {
                async_write_impl();
            }
        });
    }

    void async_write_impl()
    {
        auto self(this->shared_from_this());
        boost::asio::async_write(socket_, boost::asio::buffer(send_queue_.front()),
                                 [this, self](boost::system::error_code ec, std::size_t)
        {
            if (!ec)
            {
                send_queue_.pop_front();
                if (!send_queue_.empty())
                {
                    async_write_impl();
                }
            }
            else
            {
                log_warn(ec.message());
                send_queue_.clear();
                handle_error();
            }
        });
    }

    void handle_error()
    {
        if (req_head_.flag.type == client_type::sub_client)
        {
            handle_error_(this->shared_from_this());
        }
    }

private:
    boost::asio::io_service& ios_;
    boost::asio::ip::tcp::socket socket_;
    char req_head_buf_[request_header_len];
    request_header req_head_;
    std::vector<char> content_;
    std::size_t timeout_milli_ = 0;
    router_callback route_;
    handle_error_callback handle_error_;
    async_send_queue send_queue_;
};

}
}

<|endoftext|>


<commit_before>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "mpannableviewportlayout.h"

#include <QGraphicsWidget>

MPannableViewportLayout::MPannableViewportLayout(QGraphicsLayoutItem *parent)
    : QGraphicsLinearLayout(parent),
      pannedWidget(0),
      panningDirections(0)
{
}

void MPannableViewportLayout::setPanningDirections(const Qt::Orientations &newDirections)
{
    panningDirections = newDirections;
}

void MPannableViewportLayout::setWidget(QGraphicsWidget *widget)
{
    if (pannedWidget) {
        removeAt(0);
    }

    pannedWidget = widget;

    if (widget) {
        addItem(widget);
    }
}

void MPannableViewportLayout::setGeometry(const QRectF &rect)
{
    QRectF unboundedRect = rect;

    if (pannedWidget) {
        if (panningDirections.testFlag(Qt::Horizontal)) {
            unboundedRect.setWidth(pannedWidget->effectiveSizeHint(Qt::PreferredSize).width());
        }

        if (panningDirections.testFlag(Qt::Vertical)) {
            unboundedRect.setHeight(pannedWidget->effectiveSizeHint(Qt::PreferredSize).height());
        }
    }

    QGraphicsLinearLayout::setGeometry(unboundedRect);
}
<commit_msg>Changes: MPannableViewportLayout - Make the central widget fill the viewport<commit_after>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "mpannableviewportlayout.h"

#include <QGraphicsWidget>

MPannableViewportLayout::MPannableViewportLayout(QGraphicsLayoutItem *parent)
    : QGraphicsLinearLayout(parent),
      pannedWidget(0),
      panningDirections(0)
{
}

void MPannableViewportLayout::setPanningDirections(const Qt::Orientations &newDirections)
{
    panningDirections = newDirections;
}

void MPannableViewportLayout::setWidget(QGraphicsWidget *widget)
{
    if (pannedWidget) {
        removeAt(0);
    }

    pannedWidget = widget;

    if (widget) {
        addItem(widget);
    }
}

void MPannableViewportLayout::setGeometry(const QRectF &rect)
{
    QRectF unboundedRect = rect;

    if (pannedWidget) {
        if (panningDirections.testFlag(Qt::Horizontal)) {
            qreal width = qMax(rect.width(), pannedWidget->effectiveSizeHint(Qt::PreferredSize).width());
            unboundedRect.setWidth(width);
        }

        if (panningDirections.testFlag(Qt::Vertical)) {
            qreal height = qMax(rect.height(), pannedWidget->effectiveSizeHint(Qt::PreferredSize).height());
            unboundedRect.setHeight(height);
        }
    }

    QGraphicsLinearLayout::setGeometry(unboundedRect);
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qv8profilerservice_p.h"
#include "qdeclarativedebugservice_p_p.h"
#include <private/qdeclarativeengine_p.h>
#include <private/qv8profiler_p.h>

#include <QtCore/QHash>

QT_BEGIN_NAMESPACE

Q_GLOBAL_STATIC(QV8ProfilerService, v8ServiceInstance)

class ByteArrayOutputStream : public v8::OutputStream
{
    QByteArray *_buffer;
public:
    ByteArrayOutputStream(QByteArray *buffer)
        : v8::OutputStream(),
          _buffer(buffer) {}
    void EndOfStream() {}
    WriteResult WriteAsciiChunk(char *data, int size)
    {
        QByteArray b(data, size);
        _buffer->append(b);
        return kContinue;
    }
};

// convert to a QByteArray that can be sent to the debug client
QByteArray QV8ProfilerData::toByteArray() const
{
    QByteArray data;
    //### using QDataStream is relatively expensive
    QDataStream ds(&data, QIODevice::WriteOnly);
    ds << messageType << filename << functionname << lineNumber << totalTime << selfTime << treeLevel;

    return data;
}

class QV8ProfilerServicePrivate : public QDeclarativeDebugServicePrivate
{
    Q_DECLARE_PUBLIC(QV8ProfilerService)

public:
    QV8ProfilerServicePrivate()
        :initialized(false)
    {
    }

    void takeSnapshot(v8::HeapSnapshot::Type);

    void printProfileTree(const v8::CpuProfileNode *node, int level = 0);
    void sendMessages();

    QList<QV8ProfilerData> m_data;

    bool initialized;
    QList<QDeclarativeEngine *> engines;
};

QV8ProfilerService::QV8ProfilerService(QObject *parent)
    : QDeclarativeDebugService(*(new QV8ProfilerServicePrivate()), QLatin1String("V8Profiler"), parent)
{
    Q_D(QV8ProfilerService);
    if (status() == Enabled) {
        // ,block mode, client attached
        while (!d->initialized)
            waitForMessage();
    }
}

QV8ProfilerService::~QV8ProfilerService()
{
}

QV8ProfilerService *QV8ProfilerService::instance()
{
    return v8ServiceInstance();
}

void QV8ProfilerService::addEngine(QDeclarativeEngine *engine)
{
    Q_D(QV8ProfilerService);
    Q_ASSERT(engine);
    Q_ASSERT(!d->engines.contains(engine));

    d->engines.append(engine);
}

void QV8ProfilerService::removeEngine(QDeclarativeEngine *engine)
{
    Q_D(QV8ProfilerService);
    Q_ASSERT(engine);
    Q_ASSERT(d->engines.contains(engine));

    d->engines.removeOne(engine);
}

void QV8ProfilerService::messageReceived(const QByteArray &message)
{
    Q_D(QV8ProfilerService);

    QDataStream ds(message);
    QByteArray command;
    QByteArray option;
    QByteArray title;
    ds >> command >> option;

    if (command == "V8PROFILER") {
        ds >>  title;
        if (option == "start") {
            startProfiling(QString::fromUtf8(title));
        } else if (option == "stop") {
            stopProfiling(QString::fromUtf8(title));
            // Send messages to client
            d->sendMessages();
        }
        d->initialized = true;
    }

    if (command == "V8SNAPSHOT") {
        if (option == "full")
            d->takeSnapshot(v8::HeapSnapshot::kFull);
        else if (option == "delete") {
            v8::HeapProfiler::DeleteAllSnapshots();
        }
    }

    QDeclarativeDebugService::messageReceived(message);
}

void QV8ProfilerService::startProfiling(const QString &title)
{
    // Start Profiling
    v8::HandleScope handle_scope;
    v8::Handle<v8::String> v8title = v8::String::New(reinterpret_cast<const uint16_t*>(title.data()), title.size());
    v8::CpuProfiler::StartProfiling(v8title);
}

void QV8ProfilerService::stopProfiling(const QString &title)
{
    Q_D(QV8ProfilerService);
    // Stop profiling
    v8::HandleScope handle_scope;
    v8::Handle<v8::String> v8title = v8::String::New(reinterpret_cast<const uint16_t*>(title.data()), title.size());
    const v8::CpuProfile *cpuProfile = v8::CpuProfiler::StopProfiling(v8title);
    if (cpuProfile) {
        // can happen at start
        const v8::CpuProfileNode *rootNode = cpuProfile->GetTopDownRoot();
        d->printProfileTree(rootNode);
    }
}

void QV8ProfilerServicePrivate::printProfileTree(const v8::CpuProfileNode *node, int level)
{
    for (int index = 0 ; index < node->GetChildrenCount() ; index++) {
        const v8::CpuProfileNode* childNode = node->GetChild(index);
        if (QV8Engine::toStringStatic(childNode->GetScriptResourceName()).length() > 0) {

            QV8ProfilerData rd = {(int)QV8ProfilerService::V8Entry, QV8Engine::toStringStatic(childNode->GetScriptResourceName()),
                QV8Engine::toStringStatic(childNode->GetFunctionName()),
                childNode->GetLineNumber(), childNode->GetTotalTime(), childNode->GetSelfTime(), level};
            m_data.append(rd);

            // different nodes might have common children: fix at client side
            if (childNode->GetChildrenCount() > 0) {
                printProfileTree(childNode, level+1);
            }
        }
    }
}

void QV8ProfilerServicePrivate::takeSnapshot(v8::HeapSnapshot::Type snapshotType)
{
    Q_Q(QV8ProfilerService);

    v8::HandleScope scope;
    v8::Local<v8::String> title = v8::String::New("");

    QByteArray jsonSnapshot;
    ByteArrayOutputStream bos(&jsonSnapshot);
    const v8::HeapSnapshot *snapshot = v8::HeapProfiler::TakeSnapshot(title, snapshotType);
    snapshot->Serialize(&bos, v8::HeapSnapshot::kJSON);

    QByteArray data;
    QDataStream ds(&data, QIODevice::WriteOnly);
    ds << (int)QV8ProfilerService::V8Snapshot << jsonSnapshot;

    q->sendMessage(data);
}

void QV8ProfilerServicePrivate::sendMessages()
{
    Q_Q(QV8ProfilerService);

    for (int i = 0; i < m_data.count(); ++i)
        q->sendMessage(m_data.at(i).toByteArray());
    m_data.clear();

    //indicate completion
    QByteArray data;
    QDataStream ds(&data, QIODevice::WriteOnly);
    ds << (int)QV8ProfilerService::V8Complete;

    q->sendMessage(data);
}

QT_END_NAMESPACE
<commit_msg>QV8Profiler: Rename the global static instance<commit_after>/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qv8profilerservice_p.h"
#include "qdeclarativedebugservice_p_p.h"
#include <private/qdeclarativeengine_p.h>
#include <private/qv8profiler_p.h>

#include <QtCore/QHash>

QT_BEGIN_NAMESPACE

Q_GLOBAL_STATIC(QV8ProfilerService, v8ProfilerInstance)

class ByteArrayOutputStream : public v8::OutputStream
{
    QByteArray *_buffer;
public:
    ByteArrayOutputStream(QByteArray *buffer)
        : v8::OutputStream(),
          _buffer(buffer) {}
    void EndOfStream() {}
    WriteResult WriteAsciiChunk(char *data, int size)
    {
        QByteArray b(data, size);
        _buffer->append(b);
        return kContinue;
    }
};

// convert to a QByteArray that can be sent to the debug client
QByteArray QV8ProfilerData::toByteArray() const
{
    QByteArray data;
    //### using QDataStream is relatively expensive
    QDataStream ds(&data, QIODevice::WriteOnly);
    ds << messageType << filename << functionname << lineNumber << totalTime << selfTime << treeLevel;

    return data;
}

class QV8ProfilerServicePrivate : public QDeclarativeDebugServicePrivate
{
    Q_DECLARE_PUBLIC(QV8ProfilerService)

public:
    QV8ProfilerServicePrivate()
        :initialized(false)
    {
    }

    void takeSnapshot(v8::HeapSnapshot::Type);

    void printProfileTree(const v8::CpuProfileNode *node, int level = 0);
    void sendMessages();

    QList<QV8ProfilerData> m_data;

    bool initialized;
    QList<QDeclarativeEngine *> engines;
};

QV8ProfilerService::QV8ProfilerService(QObject *parent)
    : QDeclarativeDebugService(*(new QV8ProfilerServicePrivate()), QLatin1String("V8Profiler"), parent)
{
    Q_D(QV8ProfilerService);
    if (status() == Enabled) {
        // ,block mode, client attached
        while (!d->initialized)
            waitForMessage();
    }
}

QV8ProfilerService::~QV8ProfilerService()
{
}

QV8ProfilerService *QV8ProfilerService::instance()
{
    return v8ProfilerInstance();
}

void QV8ProfilerService::addEngine(QDeclarativeEngine *engine)
{
    Q_D(QV8ProfilerService);
    Q_ASSERT(engine);
    Q_ASSERT(!d->engines.contains(engine));

    d->engines.append(engine);
}

void QV8ProfilerService::removeEngine(QDeclarativeEngine *engine)
{
    Q_D(QV8ProfilerService);
    Q_ASSERT(engine);
    Q_ASSERT(d->engines.contains(engine));

    d->engines.removeOne(engine);
}

void QV8ProfilerService::messageReceived(const QByteArray &message)
{
    Q_D(QV8ProfilerService);

    QDataStream ds(message);
    QByteArray command;
    QByteArray option;
    QByteArray title;
    ds >> command >> option;

    if (command == "V8PROFILER") {
        ds >>  title;
        if (option == "start") {
            startProfiling(QString::fromUtf8(title));
        } else if (option == "stop") {
            stopProfiling(QString::fromUtf8(title));
            // Send messages to client
            d->sendMessages();
        }
        d->initialized = true;
    }

    if (command == "V8SNAPSHOT") {
        if (option == "full")
            d->takeSnapshot(v8::HeapSnapshot::kFull);
        else if (option == "delete") {
            v8::HeapProfiler::DeleteAllSnapshots();
        }
    }

    QDeclarativeDebugService::messageReceived(message);
}

void QV8ProfilerService::startProfiling(const QString &title)
{
    // Start Profiling
    v8::HandleScope handle_scope;
    v8::Handle<v8::String> v8title = v8::String::New(reinterpret_cast<const uint16_t*>(title.data()), title.size());
    v8::CpuProfiler::StartProfiling(v8title);
}

void QV8ProfilerService::stopProfiling(const QString &title)
{
    Q_D(QV8ProfilerService);
    // Stop profiling
    v8::HandleScope handle_scope;
    v8::Handle<v8::String> v8title = v8::String::New(reinterpret_cast<const uint16_t*>(title.data()), title.size());
    const v8::CpuProfile *cpuProfile = v8::CpuProfiler::StopProfiling(v8title);
    if (cpuProfile) {
        // can happen at start
        const v8::CpuProfileNode *rootNode = cpuProfile->GetTopDownRoot();
        d->printProfileTree(rootNode);
    }
}

void QV8ProfilerServicePrivate::printProfileTree(const v8::CpuProfileNode *node, int level)
{
    for (int index = 0 ; index < node->GetChildrenCount() ; index++) {
        const v8::CpuProfileNode* childNode = node->GetChild(index);
        if (QV8Engine::toStringStatic(childNode->GetScriptResourceName()).length() > 0) {

            QV8ProfilerData rd = {(int)QV8ProfilerService::V8Entry, QV8Engine::toStringStatic(childNode->GetScriptResourceName()),
                QV8Engine::toStringStatic(childNode->GetFunctionName()),
                childNode->GetLineNumber(), childNode->GetTotalTime(), childNode->GetSelfTime(), level};
            m_data.append(rd);

            // different nodes might have common children: fix at client side
            if (childNode->GetChildrenCount() > 0) {
                printProfileTree(childNode, level+1);
            }
        }
    }
}

void QV8ProfilerServicePrivate::takeSnapshot(v8::HeapSnapshot::Type snapshotType)
{
    Q_Q(QV8ProfilerService);

    v8::HandleScope scope;
    v8::Local<v8::String> title = v8::String::New("");

    QByteArray jsonSnapshot;
    ByteArrayOutputStream bos(&jsonSnapshot);
    const v8::HeapSnapshot *snapshot = v8::HeapProfiler::TakeSnapshot(title, snapshotType);
    snapshot->Serialize(&bos, v8::HeapSnapshot::kJSON);

    QByteArray data;
    QDataStream ds(&data, QIODevice::WriteOnly);
    ds << (int)QV8ProfilerService::V8Snapshot << jsonSnapshot;

    q->sendMessage(data);
}

void QV8ProfilerServicePrivate::sendMessages()
{
    Q_Q(QV8ProfilerService);

    for (int i = 0; i < m_data.count(); ++i)
        q->sendMessage(m_data.at(i).toByteArray());
    m_data.clear();

    //indicate completion
    QByteArray data;
    QDataStream ds(&data, QIODevice::WriteOnly);
    ds << (int)QV8ProfilerService::V8Complete;

    q->sendMessage(data);
}

QT_END_NAMESPACE
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013, Georgia Tech Research Corporation
 * All rights reserved.
 *
 * Author(s): Jeongseok Lee <jslee02@gmail.com>
 *
 * Geoorgia Tech Graphics Lab and Humanoid Robotics Lab
 *
 * Directed by Prof. C. Karen Liu and Prof. Mike Stilman
 * <karenliu@cc.gatech.edu> <mstilman@cc.gatech.edu>
 *
 * This file is provided under the following "BSD-style" License:
 *   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 of conditions 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 materials provided
 *     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 "dart/dynamics/FreeJoint.h"

#include <string>

#include "dart/math/Helpers.h"
#include "dart/math/Geometry.h"

namespace dart {
namespace dynamics {

FreeJoint::FreeJoint(const std::string& _name)
  : Joint(FREE, _name),
    mT_Joint(Eigen::Isometry3d::Identity()) {
  mGenCoords.push_back(&mCoordinate[0]);
  mGenCoords.push_back(&mCoordinate[1]);
  mGenCoords.push_back(&mCoordinate[2]);
  mGenCoords.push_back(&mCoordinate[3]);
  mGenCoords.push_back(&mCoordinate[4]);
  mGenCoords.push_back(&mCoordinate[5]);

  mS = Eigen::Matrix<double, 6, 6>::Zero();
  mdS = Eigen::Matrix<double, 6, 6>::Zero();

  mSpringStiffness.resize(6, 0.0);
  mDampingCoefficient.resize(6, 0.0);
  mRestPosition.resize(6, 0.0);
}

FreeJoint::~FreeJoint() {
}

void FreeJoint::updateTransform() {
  Eigen::Vector3d q1(mCoordinate[0].get_q(),
      mCoordinate[1].get_q(),
      mCoordinate[2].get_q());
  Eigen::Vector3d q2(mCoordinate[3].get_q(),
      mCoordinate[4].get_q(),
      mCoordinate[5].get_q());

  // TODO(JS): This is workaround for Issue #122.
  mT_Joint = math::expMap(get_q());

  mT = mT_ParentBodyToJoint * mT_Joint * mT_ChildBodyToJoint.inverse();

  assert(math::verifyTransform(mT));
}

void FreeJoint::updateTransform_Issue122(double _timeStep) {
  mT_Joint = mT_Joint * math::expMap(_timeStep * get_dq());

  set_q(math::logMap(mT_Joint));

  mT = mT_ParentBodyToJoint * mT_Joint * mT_ChildBodyToJoint.inverse();

  assert(math::verifyTransform(mT));
}

void FreeJoint::updateJacobian() {
  Eigen::Vector3d q(mCoordinate[0].get_q(),
      mCoordinate[1].get_q(),
      mCoordinate[2].get_q());

  Eigen::Matrix3d J = math::expMapJac(q);

  Eigen::Vector6d J0;
  Eigen::Vector6d J1;
  Eigen::Vector6d J2;
  Eigen::Vector6d J3;
  Eigen::Vector6d J4;
  Eigen::Vector6d J5;

  J0 << J(0, 0), J(0, 1), J(0, 2), 0, 0, 0;
  J1 << J(1, 0), J(1, 1), J(1, 2), 0, 0, 0;
  J2 << J(2, 0), J(2, 1), J(2, 2), 0, 0, 0;
  J3 << 0, 0, 0, 1, 0, 0;
  J4 << 0, 0, 0, 0, 1, 0;
  J5 << 0, 0, 0, 0, 0, 1;

  mS.col(0) = math::AdT(mT_ChildBodyToJoint, J0);
  mS.col(1) = math::AdT(mT_ChildBodyToJoint, J1);
  mS.col(2) = math::AdT(mT_ChildBodyToJoint, J2);
  mS.col(3) = math::AdT(mT_ChildBodyToJoint * math::expAngular(-q), J3);
  mS.col(4) = math::AdT(mT_ChildBodyToJoint * math::expAngular(-q), J4);
  mS.col(5) = math::AdT(mT_ChildBodyToJoint * math::expAngular(-q), J5);

  assert(!math::isNan(mS));
}

void FreeJoint::updateJacobian_Issue122() {
  Eigen::Vector6d J0 = Eigen::Vector6d::Zero();
  Eigen::Vector6d J1 = Eigen::Vector6d::Zero();
  Eigen::Vector6d J2 = Eigen::Vector6d::Zero();
  Eigen::Vector6d J3 = Eigen::Vector6d::Zero();
  Eigen::Vector6d J4 = Eigen::Vector6d::Zero();
  Eigen::Vector6d J5 = Eigen::Vector6d::Zero();

  J0[0] = 1.0;
  J1[1] = 1.0;
  J2[2] = 1.0;
  J3[3] = 1.0;
  J4[4] = 1.0;
  J5[5] = 1.0;

  mS.col(0) = math::AdT(mT_ChildBodyToJoint, J0);
  mS.col(1) = math::AdT(mT_ChildBodyToJoint, J1);
  mS.col(2) = math::AdT(mT_ChildBodyToJoint, J2);
  mS.col(3) = math::AdT(mT_ChildBodyToJoint, J3);
  mS.col(4) = math::AdT(mT_ChildBodyToJoint, J4);
  mS.col(5) = math::AdT(mT_ChildBodyToJoint, J5);

  assert(!math::isNan(mS));
}

void FreeJoint::updateJacobianTimeDeriv() {
  Eigen::Vector3d q(mCoordinate[0].get_q(),
      mCoordinate[1].get_q(),
      mCoordinate[2].get_q());
  Eigen::Vector3d dq(mCoordinate[0].get_dq(),
      mCoordinate[1].get_dq(),
      mCoordinate[2].get_dq());

  Eigen::Matrix3d dJ = math::expMapJacDot(q, dq);

  Eigen::Vector6d dJ0;
  Eigen::Vector6d dJ1;
  Eigen::Vector6d dJ2;
  Eigen::Vector6d J3;
  Eigen::Vector6d J4;
  Eigen::Vector6d J5;

  dJ0 << dJ(0, 0), dJ(0, 1), dJ(0, 2), 0, 0, 0;
  dJ1 << dJ(1, 0), dJ(1, 1), dJ(1, 2), 0, 0, 0;
  dJ2 << dJ(2, 0), dJ(2, 1), dJ(2, 2), 0, 0, 0;
  J3 << 0, 0, 0, 1, 0, 0;
  J4 << 0, 0, 0, 0, 1, 0;
  J5 << 0, 0, 0, 0, 0, 1;

  mdS.col(0) = math::AdT(mT_ChildBodyToJoint, dJ0);
  mdS.col(1) = math::AdT(mT_ChildBodyToJoint, dJ1);
  mdS.col(2) = math::AdT(mT_ChildBodyToJoint, dJ2);
  mdS.col(3) =
      -math::ad(mS.leftCols<3>() * get_dq().head<3>(),
                math::AdT(mT_ChildBodyToJoint * math::expAngular(-q), J3));
  mdS.col(4) =
      -math::ad(mS.leftCols<3>() * get_dq().head<3>(),
                math::AdT(mT_ChildBodyToJoint * math::expAngular(-q), J4));
  mdS.col(5) =
      -math::ad(mS.leftCols<3>() * get_dq().head<3>(),
                math::AdT(mT_ChildBodyToJoint * math::expAngular(-q), J5));

  assert(!math::isNan(mdS));
}

void FreeJoint::updateJacobianTimeDeriv_Issue122() {
  // mdS == 0
  assert(mdS == Eigen::MatrixXd::Zero(6, 6));
}

void FreeJoint::clampRotation() {
  for (int i = 0; i < 3; i++) {
    if (mCoordinate[i].get_q() > M_PI)
      mCoordinate[i].set_q(mCoordinate[i].get_q() - 2*M_PI);
    if (mCoordinate[i].get_q() < -M_PI)
      mCoordinate[i].set_q(mCoordinate[i].get_q() + 2*M_PI);
  }
}

}  // namespace dynamics
}  // namespace dart
<commit_msg>Clean up FreeJoint.cpp<commit_after>/*
 * Copyright (c) 2013, Georgia Tech Research Corporation
 * All rights reserved.
 *
 * Author(s): Jeongseok Lee <jslee02@gmail.com>
 *
 * Geoorgia Tech Graphics Lab and Humanoid Robotics Lab
 *
 * Directed by Prof. C. Karen Liu and Prof. Mike Stilman
 * <karenliu@cc.gatech.edu> <mstilman@cc.gatech.edu>
 *
 * This file is provided under the following "BSD-style" License:
 *   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 of conditions 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 materials provided
 *     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 "dart/dynamics/FreeJoint.h"

#include <string>

#include "dart/math/Helpers.h"
#include "dart/math/Geometry.h"

namespace dart {
namespace dynamics {

FreeJoint::FreeJoint(const std::string& _name)
  : Joint(FREE, _name),
    mT_Joint(Eigen::Isometry3d::Identity()) {
  mGenCoords.push_back(&mCoordinate[0]);
  mGenCoords.push_back(&mCoordinate[1]);
  mGenCoords.push_back(&mCoordinate[2]);
  mGenCoords.push_back(&mCoordinate[3]);
  mGenCoords.push_back(&mCoordinate[4]);
  mGenCoords.push_back(&mCoordinate[5]);

  mS = Eigen::Matrix<double, 6, 6>::Zero();
  mdS = Eigen::Matrix<double, 6, 6>::Zero();

  mSpringStiffness.resize(6, 0.0);
  mDampingCoefficient.resize(6, 0.0);
  mRestPosition.resize(6, 0.0);
}

FreeJoint::~FreeJoint() {
}

void FreeJoint::updateTransform() {
  // TODO(JS): This is workaround for Issue #122.
  mT_Joint = math::expMap(get_q());

  mT = mT_ParentBodyToJoint * mT_Joint * mT_ChildBodyToJoint.inverse();

  assert(math::verifyTransform(mT));
}

void FreeJoint::updateTransform_Issue122(double _timeStep) {
  mT_Joint = mT_Joint * math::expMap(_timeStep * get_dq());

  set_q(math::logMap(mT_Joint));

  mT = mT_ParentBodyToJoint * mT_Joint * mT_ChildBodyToJoint.inverse();

  assert(math::verifyTransform(mT));
}

void FreeJoint::updateJacobian() {
  Eigen::Vector3d q(mCoordinate[0].get_q(),
                    mCoordinate[1].get_q(),
                    mCoordinate[2].get_q());

  Eigen::Matrix3d J = math::expMapJac(q);

  Eigen::Vector6d J0;
  Eigen::Vector6d J1;
  Eigen::Vector6d J2;
  Eigen::Vector6d J3;
  Eigen::Vector6d J4;
  Eigen::Vector6d J5;

  J0 << J(0, 0), J(0, 1), J(0, 2), 0, 0, 0;
  J1 << J(1, 0), J(1, 1), J(1, 2), 0, 0, 0;
  J2 << J(2, 0), J(2, 1), J(2, 2), 0, 0, 0;
  J3 << 0, 0, 0, 1, 0, 0;
  J4 << 0, 0, 0, 0, 1, 0;
  J5 << 0, 0, 0, 0, 0, 1;

  mS.col(0) = math::AdT(mT_ChildBodyToJoint, J0);
  mS.col(1) = math::AdT(mT_ChildBodyToJoint, J1);
  mS.col(2) = math::AdT(mT_ChildBodyToJoint, J2);
  mS.col(3) = math::AdT(mT_ChildBodyToJoint * math::expAngular(-q), J3);
  mS.col(4) = math::AdT(mT_ChildBodyToJoint * math::expAngular(-q), J4);
  mS.col(5) = math::AdT(mT_ChildBodyToJoint * math::expAngular(-q), J5);

  assert(!math::isNan(mS));
}

void FreeJoint::updateJacobian_Issue122() {
  Eigen::Vector6d J0 = Eigen::Vector6d::Zero();
  Eigen::Vector6d J1 = Eigen::Vector6d::Zero();
  Eigen::Vector6d J2 = Eigen::Vector6d::Zero();
  Eigen::Vector6d J3 = Eigen::Vector6d::Zero();
  Eigen::Vector6d J4 = Eigen::Vector6d::Zero();
  Eigen::Vector6d J5 = Eigen::Vector6d::Zero();

  J0[0] = 1.0;
  J1[1] = 1.0;
  J2[2] = 1.0;
  J3[3] = 1.0;
  J4[4] = 1.0;
  J5[5] = 1.0;

  mS.col(0) = math::AdT(mT_ChildBodyToJoint, J0);
  mS.col(1) = math::AdT(mT_ChildBodyToJoint, J1);
  mS.col(2) = math::AdT(mT_ChildBodyToJoint, J2);
  mS.col(3) = math::AdT(mT_ChildBodyToJoint, J3);
  mS.col(4) = math::AdT(mT_ChildBodyToJoint, J4);
  mS.col(5) = math::AdT(mT_ChildBodyToJoint, J5);

  assert(!math::isNan(mS));
}

void FreeJoint::updateJacobianTimeDeriv() {
  Eigen::Vector3d q(mCoordinate[0].get_q(),
                    mCoordinate[1].get_q(),
                    mCoordinate[2].get_q());
  Eigen::Vector3d dq(mCoordinate[0].get_dq(),
                     mCoordinate[1].get_dq(),
                     mCoordinate[2].get_dq());

  Eigen::Matrix3d dJ = math::expMapJacDot(q, dq);

  Eigen::Vector6d dJ0;
  Eigen::Vector6d dJ1;
  Eigen::Vector6d dJ2;
  Eigen::Vector6d J3;
  Eigen::Vector6d J4;
  Eigen::Vector6d J5;

  dJ0 << dJ(0, 0), dJ(0, 1), dJ(0, 2), 0, 0, 0;
  dJ1 << dJ(1, 0), dJ(1, 1), dJ(1, 2), 0, 0, 0;
  dJ2 << dJ(2, 0), dJ(2, 1), dJ(2, 2), 0, 0, 0;
  J3 << 0, 0, 0, 1, 0, 0;
  J4 << 0, 0, 0, 0, 1, 0;
  J5 << 0, 0, 0, 0, 0, 1;

  mdS.col(0) = math::AdT(mT_ChildBodyToJoint, dJ0);
  mdS.col(1) = math::AdT(mT_ChildBodyToJoint, dJ1);
  mdS.col(2) = math::AdT(mT_ChildBodyToJoint, dJ2);
  mdS.col(3) =
      -math::ad(mS.leftCols<3>() * get_dq().head<3>(),
                math::AdT(mT_ChildBodyToJoint * math::expAngular(-q), J3));
  mdS.col(4) =
      -math::ad(mS.leftCols<3>() * get_dq().head<3>(),
                math::AdT(mT_ChildBodyToJoint * math::expAngular(-q), J4));
  mdS.col(5) =
      -math::ad(mS.leftCols<3>() * get_dq().head<3>(),
                math::AdT(mT_ChildBodyToJoint * math::expAngular(-q), J5));

  assert(!math::isNan(mdS));
}

void FreeJoint::updateJacobianTimeDeriv_Issue122() {
  // mdS == 0
  assert(mdS == Eigen::MatrixXd::Zero(6, 6));
}

void FreeJoint::clampRotation() {
  for (int i = 0; i < 3; i++) {
    if (mCoordinate[i].get_q() > M_PI)
      mCoordinate[i].set_q(mCoordinate[i].get_q() - 2*M_PI);
    if (mCoordinate[i].get_q() < -M_PI)
      mCoordinate[i].set_q(mCoordinate[i].get_q() + 2*M_PI);
  }
}

}  // namespace dynamics
}  // namespace dart
<|endoftext|>


<commit_before>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

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 <memory>
#include <string>
#include <utility>
#include <vector>

#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "tensorflow/core/framework/step_stats.pb.h"
#include "tensorflow/core/platform/errors.h"
#include "tensorflow/core/platform/status.h"
#include "tensorflow/core/platform/types.h"
#include "tensorflow/core/profiler/lib/profiler_factory.h"
#include "tensorflow/core/profiler/lib/profiler_interface.h"
#include "tensorflow/core/profiler/profiler_options.pb.h"
#include "tensorflow/core/profiler/protobuf/xplane.pb.h"
#include "tensorflow/core/profiler/utils/xplane_schema.h"
#include "tensorflow/core/tpu/tpu_api.h"
#include "tensorflow/core/tpu/tpu_initializer_helper.h"
#include "tensorflow/core/tpu/tpu_ops_c_api.h"
#include "tensorflow/stream_executor/tpu/status_helper.h"

namespace tensorflow {
namespace profiler {
namespace {

// Tpu implementation of ProfilerInterface.
//
// Thread-safety: This class is go/thread-compatible.
class TpuTracer : public ProfilerInterface {
 public:
  explicit TpuTracer();
  ~TpuTracer() override;

  Status Start() override;

  Status Stop() override;

  // Unsupported.
  Status CollectData(RunMetadata* run_metadata) override;

  Status CollectData(XSpace* space) override;

 private:
  TpuProfiler* tpu_profiler_;
};

TpuTracer::TpuTracer() {
  StatusHelper status;
  tpu::OpsApiFn()->TpuProfiler_CreateFn(&tpu_profiler_, status.c_status);
  if (!status.ok()) {
    LOG(ERROR) << status.status().error_message();
  }
}

TpuTracer::~TpuTracer() {
  tpu::OpsApiFn()->TpuProfiler_DestroyFn(tpu_profiler_);
}

Status TpuTracer::Start() {
  StatusHelper status;
  tpu::OpsApiFn()->TpuProfiler_StartFn(tpu_profiler_, status.c_status);
  if (!status.ok()) {
    LOG(ERROR) << "TPU tracer failed to start.";
    return status.status();
  }
  return Status::OK();
}

Status TpuTracer::Stop() {
  StatusHelper status;
  tpu::OpsApiFn()->TpuProfiler_StopFn(tpu_profiler_, status.c_status);
  if (!status.ok()) {
    LOG(ERROR) << "TPU tracer failed to stop.";
    return status.status();
  }
  return Status::OK();
}

Status TpuTracer::CollectData(RunMetadata* run_metadata) {
  // Unsupported
  return Status::OK();
}

Status TpuTracer::CollectData(XSpace* space) {
  StatusHelper status;
  // Get size of buffer required for TPU driver to serialize XSpace into.
  size_t size_in_bytes;
  tpu::OpsApiFn()->TpuProfiler_CollectDataFn(tpu_profiler_, status.c_status,
                                             /*buffer=*/nullptr,
                                             &size_in_bytes);
  // Prepare an appropriately sized buffer.
  if (size_in_bytes > 0) {
    std::vector<uint8_t> buffer(size_in_bytes);
    tpu::OpsApiFn()->TpuProfiler_CollectDataFn(tpu_profiler_, status.c_status,
                                               buffer.data(), &size_in_bytes);
    // Deserialize XSpace from the buffer and return it.
    XSpace tpu_space;
    tpu_space.ParseFromArray(buffer.data(), buffer.size());
    for (XPlane& tpu_plane : *tpu_space.mutable_planes()) {
      XPlane* plane = space->add_planes();
      plane->Swap(&tpu_plane);
    }
  }
  if (!status.ok()) {
    LOG(ERROR) << "TPU tracer failed to collect data.";
    return status.status();
  }
  return Status::OK();
}

}  // namespace

// Not in anonymous namespace for testing purposes.
std::unique_ptr<ProfilerInterface> CreateTpuTracer(
    const ProfileOptions& options) {
  if (options.device_type() != ProfileOptions::TPU &&
      options.device_type() != ProfileOptions::UNSPECIFIED) {
    return nullptr;
  }
  return absl::make_unique<TpuTracer>();
}

auto register_tpu_tracer_factory = [] {
  if (tensorflow::tpu::TryAcquireTpuLock()) {
    RegisterProfilerFactory(&CreateTpuTracer);
  }
  return 0;
}();

}  // namespace profiler
}  // namespace tensorflow
<commit_msg>Don't create TpuTracer if the TPU C API isn't initialized.<commit_after>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

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 <memory>
#include <string>
#include <utility>
#include <vector>

#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "tensorflow/core/framework/step_stats.pb.h"
#include "tensorflow/core/platform/errors.h"
#include "tensorflow/core/platform/status.h"
#include "tensorflow/core/platform/types.h"
#include "tensorflow/core/profiler/lib/profiler_factory.h"
#include "tensorflow/core/profiler/lib/profiler_interface.h"
#include "tensorflow/core/profiler/profiler_options.pb.h"
#include "tensorflow/core/profiler/protobuf/xplane.pb.h"
#include "tensorflow/core/profiler/utils/xplane_schema.h"
#include "tensorflow/core/tpu/tpu_api.h"
#include "tensorflow/core/tpu/tpu_initializer_helper.h"
#include "tensorflow/core/tpu/tpu_ops_c_api.h"
#include "tensorflow/stream_executor/tpu/status_helper.h"

namespace tensorflow {
namespace profiler {
namespace {

// Tpu implementation of ProfilerInterface.
//
// Thread-safety: This class is go/thread-compatible.
class TpuTracer : public ProfilerInterface {
 public:
  explicit TpuTracer();
  ~TpuTracer() override;

  Status Start() override;

  Status Stop() override;

  // Unsupported.
  Status CollectData(RunMetadata* run_metadata) override;

  Status CollectData(XSpace* space) override;

 private:
  TpuProfiler* tpu_profiler_;
};

TpuTracer::TpuTracer() {
  StatusHelper status;
  tpu::OpsApiFn()->TpuProfiler_CreateFn(&tpu_profiler_, status.c_status);
  if (!status.ok()) {
    LOG(ERROR) << status.status().error_message();
  }
}

TpuTracer::~TpuTracer() {
  tpu::OpsApiFn()->TpuProfiler_DestroyFn(tpu_profiler_);
}

Status TpuTracer::Start() {
  StatusHelper status;
  tpu::OpsApiFn()->TpuProfiler_StartFn(tpu_profiler_, status.c_status);
  if (!status.ok()) {
    LOG(ERROR) << "TPU tracer failed to start.";
    return status.status();
  }
  return Status::OK();
}

Status TpuTracer::Stop() {
  StatusHelper status;
  tpu::OpsApiFn()->TpuProfiler_StopFn(tpu_profiler_, status.c_status);
  if (!status.ok()) {
    LOG(ERROR) << "TPU tracer failed to stop.";
    return status.status();
  }
  return Status::OK();
}

Status TpuTracer::CollectData(RunMetadata* run_metadata) {
  // Unsupported
  return Status::OK();
}

Status TpuTracer::CollectData(XSpace* space) {
  StatusHelper status;
  // Get size of buffer required for TPU driver to serialize XSpace into.
  size_t size_in_bytes;
  tpu::OpsApiFn()->TpuProfiler_CollectDataFn(tpu_profiler_, status.c_status,
                                             /*buffer=*/nullptr,
                                             &size_in_bytes);
  // Prepare an appropriately sized buffer.
  if (size_in_bytes > 0) {
    std::vector<uint8_t> buffer(size_in_bytes);
    tpu::OpsApiFn()->TpuProfiler_CollectDataFn(tpu_profiler_, status.c_status,
                                               buffer.data(), &size_in_bytes);
    // Deserialize XSpace from the buffer and return it.
    XSpace tpu_space;
    tpu_space.ParseFromArray(buffer.data(), buffer.size());
    for (XPlane& tpu_plane : *tpu_space.mutable_planes()) {
      XPlane* plane = space->add_planes();
      plane->Swap(&tpu_plane);
    }
  }
  if (!status.ok()) {
    LOG(ERROR) << "TPU tracer failed to collect data.";
    return status.status();
  }
  return Status::OK();
}

}  // namespace

// Not in anonymous namespace for testing purposes.
std::unique_ptr<ProfilerInterface> CreateTpuTracer(
    const ProfileOptions& options) {
  if (options.device_type() != ProfileOptions::TPU &&
      options.device_type() != ProfileOptions::UNSPECIFIED) {
    return nullptr;
  }
  // Don't attempt to create a TpuTracer if the TPU C API isn't initialized.
  if (tpu::OpsApiFn()->TpuProfiler_CreateFn == nullptr) {
    return nullptr;
  }
  return absl::make_unique<TpuTracer>();
}

auto register_tpu_tracer_factory = [] {
  if (tensorflow::tpu::TryAcquireTpuLock()) {
    RegisterProfilerFactory(&CreateTpuTracer);
  }
  return 0;
}();

}  // namespace profiler
}  // namespace tensorflow
<|endoftext|>


<commit_before>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow/lite/tools/optimize/operator_property.h"

#include "tensorflow/lite/schema/schema_generated.h"

namespace tflite {
namespace optimize {
namespace operator_property {

namespace {

// The op as well as it variants.
// TODO(jianlijianli): extend it to support ops that has multiple variants.
struct OpVariant {
  BuiltinOperator op_code;
};

const OpVariant GetOperatorVariant(const ModelT* model, int subgraph_index,
                                   int op_index) {
  OpVariant op_variant;
  OperatorT* op =
      model->subgraphs.at(subgraph_index)->operators[op_index].get();
  op_variant.op_code = model->operator_codes[op->opcode_index]->builtin_code;
  return op_variant;
}
}  // namespace

OperatorProperty GetOperatorProperty(const ModelT* model, int subgraph_index,
                                     int op_index) {
  OpVariant op_variant = GetOperatorVariant(model, subgraph_index, op_index);
  BuiltinOperator op_code = op_variant.op_code;
  OperatorProperty property;
  switch (op_code) {
    case BuiltinOperator_ADD:
      property.inputs = {{0, {}}, {1, {}}};
      property.outputs = {{0, {}}};
      property.version = 2;
      break;
    case BuiltinOperator_ARG_MAX:
      property.inputs = {{0, {}}};
      // ArgMax has no quantizable output.
      property.version = 2;
      break;
    case BuiltinOperator_AVERAGE_POOL_2D:
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 2;
      break;
    case BuiltinOperator_BATCH_TO_SPACE_ND:
    case BuiltinOperator_SPACE_TO_BATCH_ND:
    case BuiltinOperator_SPACE_TO_DEPTH:
      // We skip inputs 1 and 2 since they aren't real valued (they are shapes).
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 2;
      break;
    case BuiltinOperator_SPLIT:
      // We skip input 0 since it is the split dim which is not real valued.
      property.inputs = {{1, {}}};
      property.arbitrary_outputs = true;
      property.restrict_same_input_output_scale = true;
      property.version = 2;
      break;
    case BuiltinOperator_CONCATENATION:
      property.arbitrary_inputs = true;
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 2;
      break;
    case BuiltinOperator_CONV_2D: {
      TensorProperty tensor_property;
      tensor_property.per_axis = true;
      tensor_property.per_axis_index = 0;
      tensor_property.symmetric = true;
      property.inputs = {{0, {}}, {1, tensor_property}};
      property.outputs = {{0, {}}};
      property.biases = {2};
      property.version = 3;
      break;
    }
    case BuiltinOperator_TRANSPOSE_CONV: {
      TensorProperty tensor_property;
      tensor_property.per_axis = true;
      tensor_property.per_axis_index = 0;
      tensor_property.symmetric = true;
      property.inputs = {{1, tensor_property}, {2, {}}};
      property.outputs = {{0, {}}};
      property.version = 2;
      break;
    }
    case BuiltinOperator_DEPTHWISE_CONV_2D: {
      TensorProperty tensor_property;
      tensor_property.per_axis = true;
      tensor_property.per_axis_index = 3;
      tensor_property.symmetric = true;
      property.inputs = {
          {0, {}},
          {1, tensor_property},
      };
      property.outputs = {{0, {}}};
      property.biases = {2};
      property.version = 3;
      break;
    }
    case BuiltinOperator_EQUAL:
    case BuiltinOperator_NOT_EQUAL:
    case BuiltinOperator_GREATER:
    case BuiltinOperator_GREATER_EQUAL:
    case BuiltinOperator_LESS:
    case BuiltinOperator_LESS_EQUAL:
      property.inputs = {{0, {}}, {1, {}}};
      // Comparisons have no quantizable outputs.
      property.version = 2;
      break;
    case BuiltinOperator_EXPAND_DIMS:
      // We skip input 1 as it is not real valued (it's the index of axis) and
      // hence does not need to be quantized.
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.version = 1;
      break;
    case BuiltinOperator_FULLY_CONNECTED: {
      TensorProperty tensor_property;
      tensor_property.symmetric = true;
      property.inputs = {{0, {}}, {1, tensor_property}};
      property.outputs = {{0, {}}};
      property.biases = {2};
      property.version = 4;
      break;
    }
    case BuiltinOperator_GATHER:
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 2;
      break;
    case BuiltinOperator_HARD_SWISH: {
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.version = 1;
      break;
    }
    case BuiltinOperator_LOG_SOFTMAX: {
      property.inputs = {{0, {}}};
      // LogSoftmax requires output with 16/256 as scale and 127 as zero point.
      TensorProperty tensor_property;
      tensor_property.restriction = true;
      tensor_property.restricted_value = {16.0 / 256.0, 127};
      property.outputs = {{0, tensor_property}};
      property.version = 2;
      break;
    }
    case BuiltinOperator_LOGISTIC: {
      property.inputs = {{0, {}}};
      // Logistic requires output with 1/256 as scale and -128 as zero point.
      TensorProperty tensor_property;
      tensor_property.restriction = true;
      tensor_property.restricted_value = {1 / 256.0, -128};
      property.outputs = {{0, tensor_property}};
      property.version = 2;
      break;
    }
    case BuiltinOperator_LSTM: {
      // TODO(jianlijianli): extend LSTM op spec to inlucde input, bias etc.
      // TODO(jianlijianli): extend this to other variants of LSTM.
      // LSTM needs 5 intermediate tensors. This agrees with the fully quantized
      // kernels in lstm_eval.cc
      static const float alpha = static_cast<float>(std::pow(2, -10));

      TensorProperty tensor_property_12;
      tensor_property_12.use_derived_scale = true;
      tensor_property_12.number_of_bits = 32;
      tensor_property_12.derived_scale = {{20}, {}, {alpha}};
      TensorProperty tensor_property_13;
      tensor_property_13.use_derived_scale = true;
      tensor_property_13.number_of_bits = 32;
      tensor_property_13.derived_scale = {{21}, {}, {alpha}};
      TensorProperty tensor_property_14;
      tensor_property_14.use_derived_scale = true;
      tensor_property_14.number_of_bits = 32;
      tensor_property_14.derived_scale = {{22}, {}, {alpha}};
      TensorProperty tensor_property_15;
      tensor_property_15.use_derived_scale = true;
      tensor_property_15.number_of_bits = 32;
      tensor_property_15.derived_scale = {{23}, {}, {alpha}};
      TensorProperty tensor_property_17;
      tensor_property_17.use_derived_scale = true;
      tensor_property_17.number_of_bits = 32;
      tensor_property_17.derived_scale = {{16}, {4}, {}};
      TensorProperty tensor_property_19;
      tensor_property_19.extend_to_power_of_two = true;
      tensor_property_19.number_of_bits = 16;
      tensor_property_19.state_tensor = true;
      tensor_property_19.symmetric = true;
      TensorProperty tensor_property_20;
      tensor_property_20.number_of_bits = 16;
      tensor_property_20.symmetric = true;

      property.inputs = {
          {0, {}},
          {1, {}},
          {2, {}},
          {3, {}},
          {4, {}},
          {5, {}},
          {6, {}},
          {7, {}},
          {8, {}},
          {9, {}},
          {10, {}},
          {11, {}},
          {16, {}},
          {19, tensor_property_19},
          {20, tensor_property_20},
          {21, tensor_property_20},
          {22, tensor_property_20},
          {23, tensor_property_20},
          {12, tensor_property_12},
          {13, tensor_property_13},
          {14, tensor_property_14},
          {15, tensor_property_15},
          {17, tensor_property_17},
      };
      property.outputs = {{0, {}}};
      property.intermediates = {
          {0, tensor_property_20},
          {1, tensor_property_20},
          {2, tensor_property_20},
          {3, tensor_property_20},
          {4, {}},
      };
      property.restrict_scale = {{18, 0}};
      property.version = 2;
      break;
    }
    case BuiltinOperator_L2_NORMALIZATION: {
      property.inputs = {{0, {}}};
      // L2 Norm requires output with 1/128 as scale and 0 as zero point.
      TensorProperty tensor_property;
      tensor_property.restriction = true;
      tensor_property.restricted_value = {1 / 128.0, 0};
      property.outputs = {{0, tensor_property}};
      property.version = 2;
      break;
    }
    case BuiltinOperator_MAX_POOL_2D:
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 2;
      break;
    case BuiltinOperator_MAXIMUM:
      property.arbitrary_inputs = true;
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 2;
      break;
    case BuiltinOperator_MEAN:
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.version = 2;
      break;
    case BuiltinOperator_MINIMUM:
      property.arbitrary_inputs = true;
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 2;
      break;
    case BuiltinOperator_MUL:
      property.inputs = {{0, {}}, {1, {}}};
      property.outputs = {{0, {}}};
      property.version = 2;
      break;
    case BuiltinOperator_PACK:
      property.arbitrary_inputs = true;
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 2;
      break;
    case BuiltinOperator_PAD:
    case BuiltinOperator_PADV2:
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 2;
      break;
    case BuiltinOperator_QUANTIZE:
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.version = 2;
      break;
    case BuiltinOperator_RELU:
    case BuiltinOperator_RELU6:
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.version = 2;
      break;
    case BuiltinOperator_RELU_N1_TO_1:
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.version = 1;
      break;
    case BuiltinOperator_RESHAPE:
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 1;
      break;
    case BuiltinOperator_RESIZE_BILINEAR:
    case BuiltinOperator_RESIZE_NEAREST_NEIGHBOR:
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 2;
      break;
    case BuiltinOperator_SHAPE:
      property.inputs = {{0, {}}};
      // Shape has no quantizable output.
      property.version = 1;
      break;
    case BuiltinOperator_SLICE:
      // We skip inputs 1 and 2 since they aren't real valued (they are the
      // index and size).
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 2;
      break;
    case BuiltinOperator_SQUEEZE:
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 1;
      break;
    case BuiltinOperator_SOFTMAX: {
      property.inputs = {{0, {}}};
      // Softmax requires output with 1/256 as scale and -128 as zero point.
      TensorProperty tensor_property;
      tensor_property.restriction = true;
      tensor_property.restricted_value = {1 / 256.0, -128};
      property.outputs = {{0, tensor_property}};
      property.version = 2;
      break;
    }
    case BuiltinOperator_STRIDED_SLICE:
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 2;
      break;
    case BuiltinOperator_SUB:
      property.inputs = {{0, {}}, {1, {}}};
      property.outputs = {{0, {}}};
      property.version = 2;
      break;
    case BuiltinOperator_SUM:
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.version = 2;
      break;
    case BuiltinOperator_TANH: {
      property.inputs = {{0, {}}};
      // Tanh requires output with 1/128 as scale and 0 as zero point.
      TensorProperty tensor_property;
      tensor_property.restriction = true;
      tensor_property.restricted_value = {1 / 128.0, 0};
      property.outputs = {{0, tensor_property}};
      property.version = 2;
      break;
    }
    case BuiltinOperator_TRANSPOSE:
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 2;
      break;
    case BuiltinOperator_UNPACK:
      property.inputs = {{0, {}}};
      property.arbitrary_outputs = true;
      property.restrict_same_input_output_scale = true;
      property.version = 1;
      break;
    default:
      // No quantized implementation exists for this operation.
      property.quantizable = false;
  }
  return property;
}

}  // namespace operator_property
}  // namespace optimize
}  // namespace tflite
<commit_msg>Restrict LSTM operator property to support only one variant of LSTM.<commit_after>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow/lite/tools/optimize/operator_property.h"

#include "tensorflow/lite/schema/schema_generated.h"

namespace tflite {
namespace optimize {
namespace operator_property {

namespace {

// The op as well as it variants.
// TODO(jianlijianli): extend it to support ops that has multiple variants.
struct OpVariant {
  BuiltinOperator op_code;
  bool use_layer_norm = false;
  bool use_projection = false;
  bool use_peephole = false;
};

const OpVariant GetOperatorVariant(const ModelT* model, int subgraph_index,
                                   int op_index) {
  OpVariant op_variant;
  OperatorT* op =
      model->subgraphs.at(subgraph_index)->operators[op_index].get();
  op_variant.op_code = model->operator_codes[op->opcode_index]->builtin_code;
  if (op_variant.op_code == BuiltinOperator_LSTM) {
    const int cell_to_output_weight_index = 11;
    const int forget_layer_norm_coefficients_index = 21;
    const int projection_weights_index = 16;
    op_variant.use_projection = op->inputs[projection_weights_index] != -1;
    op_variant.use_peephole = op->inputs[cell_to_output_weight_index] != -1;
    if (op->inputs.size() == 20) {
      op_variant.use_layer_norm = false;
    } else {
      op_variant.use_layer_norm =
          op->inputs[forget_layer_norm_coefficients_index] != -1;
    }
  }
  return op_variant;
}
}  // namespace

OperatorProperty GetOperatorProperty(const ModelT* model, int subgraph_index,
                                     int op_index) {
  OpVariant op_variant = GetOperatorVariant(model, subgraph_index, op_index);
  BuiltinOperator op_code = op_variant.op_code;
  OperatorProperty property;
  switch (op_code) {
    case BuiltinOperator_ADD:
      property.inputs = {{0, {}}, {1, {}}};
      property.outputs = {{0, {}}};
      property.version = 2;
      break;
    case BuiltinOperator_ARG_MAX:
      property.inputs = {{0, {}}};
      // ArgMax has no quantizable output.
      property.version = 2;
      break;
    case BuiltinOperator_AVERAGE_POOL_2D:
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 2;
      break;
    case BuiltinOperator_BATCH_TO_SPACE_ND:
    case BuiltinOperator_SPACE_TO_BATCH_ND:
    case BuiltinOperator_SPACE_TO_DEPTH:
      // We skip inputs 1 and 2 since they aren't real valued (they are shapes).
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 2;
      break;
    case BuiltinOperator_SPLIT:
      // We skip input 0 since it is the split dim which is not real valued.
      property.inputs = {{1, {}}};
      property.arbitrary_outputs = true;
      property.restrict_same_input_output_scale = true;
      property.version = 2;
      break;
    case BuiltinOperator_CONCATENATION:
      property.arbitrary_inputs = true;
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 2;
      break;
    case BuiltinOperator_CONV_2D: {
      TensorProperty tensor_property;
      tensor_property.per_axis = true;
      tensor_property.per_axis_index = 0;
      tensor_property.symmetric = true;
      property.inputs = {{0, {}}, {1, tensor_property}};
      property.outputs = {{0, {}}};
      property.biases = {2};
      property.version = 3;
      break;
    }
    case BuiltinOperator_TRANSPOSE_CONV: {
      TensorProperty tensor_property;
      tensor_property.per_axis = true;
      tensor_property.per_axis_index = 0;
      tensor_property.symmetric = true;
      property.inputs = {{1, tensor_property}, {2, {}}};
      property.outputs = {{0, {}}};
      property.version = 2;
      break;
    }
    case BuiltinOperator_DEPTHWISE_CONV_2D: {
      TensorProperty tensor_property;
      tensor_property.per_axis = true;
      tensor_property.per_axis_index = 3;
      tensor_property.symmetric = true;
      property.inputs = {
          {0, {}},
          {1, tensor_property},
      };
      property.outputs = {{0, {}}};
      property.biases = {2};
      property.version = 3;
      break;
    }
    case BuiltinOperator_EQUAL:
    case BuiltinOperator_NOT_EQUAL:
    case BuiltinOperator_GREATER:
    case BuiltinOperator_GREATER_EQUAL:
    case BuiltinOperator_LESS:
    case BuiltinOperator_LESS_EQUAL:
      property.inputs = {{0, {}}, {1, {}}};
      // Comparisons have no quantizable outputs.
      property.version = 2;
      break;
    case BuiltinOperator_EXPAND_DIMS:
      // We skip input 1 as it is not real valued (it's the index of axis) and
      // hence does not need to be quantized.
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.version = 1;
      break;
    case BuiltinOperator_FULLY_CONNECTED: {
      TensorProperty tensor_property;
      tensor_property.symmetric = true;
      property.inputs = {{0, {}}, {1, tensor_property}};
      property.outputs = {{0, {}}};
      property.biases = {2};
      property.version = 4;
      break;
    }
    case BuiltinOperator_GATHER:
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 2;
      break;
    case BuiltinOperator_HARD_SWISH: {
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.version = 1;
      break;
    }
    case BuiltinOperator_LOG_SOFTMAX: {
      property.inputs = {{0, {}}};
      // LogSoftmax requires output with 16/256 as scale and 127 as zero point.
      TensorProperty tensor_property;
      tensor_property.restriction = true;
      tensor_property.restricted_value = {16.0 / 256.0, 127};
      property.outputs = {{0, tensor_property}};
      property.version = 2;
      break;
    }
    case BuiltinOperator_LOGISTIC: {
      property.inputs = {{0, {}}};
      // Logistic requires output with 1/256 as scale and -128 as zero point.
      TensorProperty tensor_property;
      tensor_property.restriction = true;
      tensor_property.restricted_value = {1 / 256.0, -128};
      property.outputs = {{0, tensor_property}};
      property.version = 2;
      break;
    }
    case BuiltinOperator_LSTM: {
      // TODO(jianlijianli): extend LSTM op spec to inlucde input, bias etc.
      // TODO(jianlijianli): extend this to other variants of LSTM.
      // LSTM needs 5 intermediate tensors. This agrees with the fully quantized
      // kernels in lstm_eval.cc
      if (op_variant.use_layer_norm && op_variant.use_projection &&
          !op_variant.use_peephole) {
        static const float alpha = static_cast<float>(std::pow(2, -10));

        TensorProperty tensor_property_12;
        tensor_property_12.use_derived_scale = true;
        tensor_property_12.number_of_bits = 32;
        tensor_property_12.derived_scale = {{20}, {}, {alpha}};
        TensorProperty tensor_property_13;
        tensor_property_13.use_derived_scale = true;
        tensor_property_13.number_of_bits = 32;
        tensor_property_13.derived_scale = {{21}, {}, {alpha}};
        TensorProperty tensor_property_14;
        tensor_property_14.use_derived_scale = true;
        tensor_property_14.number_of_bits = 32;
        tensor_property_14.derived_scale = {{22}, {}, {alpha}};
        TensorProperty tensor_property_15;
        tensor_property_15.use_derived_scale = true;
        tensor_property_15.number_of_bits = 32;
        tensor_property_15.derived_scale = {{23}, {}, {alpha}};
        TensorProperty tensor_property_17;
        tensor_property_17.use_derived_scale = true;
        tensor_property_17.number_of_bits = 32;
        tensor_property_17.derived_scale = {{16}, {4}, {}};
        TensorProperty tensor_property_19;
        tensor_property_19.extend_to_power_of_two = true;
        tensor_property_19.number_of_bits = 16;
        tensor_property_19.state_tensor = true;
        tensor_property_19.symmetric = true;
        TensorProperty tensor_property_20;
        tensor_property_20.number_of_bits = 16;
        tensor_property_20.symmetric = true;

        property.inputs = {
            {0, {}},
            {1, {}},
            {2, {}},
            {3, {}},
            {4, {}},
            {5, {}},
            {6, {}},
            {7, {}},
            {8, {}},
            {16, {}},
            {19, tensor_property_19},
            {20, tensor_property_20},
            {21, tensor_property_20},
            {22, tensor_property_20},
            {23, tensor_property_20},
            {12, tensor_property_12},
            {13, tensor_property_13},
            {14, tensor_property_14},
            {15, tensor_property_15},
            {17, tensor_property_17},
        };
        property.outputs = {{0, {}}};
        property.intermediates = {
            {0, tensor_property_20},
            {1, tensor_property_20},
            {2, tensor_property_20},
            {3, tensor_property_20},
            {4, {}},
        };
        property.restrict_scale = {{18, 0}};
        property.version = 2;
      } else {
        property.quantizable = false;
      }
      break;
    }
    case BuiltinOperator_L2_NORMALIZATION: {
      property.inputs = {{0, {}}};
      // L2 Norm requires output with 1/128 as scale and 0 as zero point.
      TensorProperty tensor_property;
      tensor_property.restriction = true;
      tensor_property.restricted_value = {1 / 128.0, 0};
      property.outputs = {{0, tensor_property}};
      property.version = 2;
      break;
    }
    case BuiltinOperator_MAX_POOL_2D:
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 2;
      break;
    case BuiltinOperator_MAXIMUM:
      property.arbitrary_inputs = true;
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 2;
      break;
    case BuiltinOperator_MEAN:
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.version = 2;
      break;
    case BuiltinOperator_MINIMUM:
      property.arbitrary_inputs = true;
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 2;
      break;
    case BuiltinOperator_MUL:
      property.inputs = {{0, {}}, {1, {}}};
      property.outputs = {{0, {}}};
      property.version = 2;
      break;
    case BuiltinOperator_PACK:
      property.arbitrary_inputs = true;
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 2;
      break;
    case BuiltinOperator_PAD:
    case BuiltinOperator_PADV2:
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 2;
      break;
    case BuiltinOperator_QUANTIZE:
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.version = 2;
      break;
    case BuiltinOperator_RELU:
    case BuiltinOperator_RELU6:
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.version = 2;
      break;
    case BuiltinOperator_RELU_N1_TO_1:
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.version = 1;
      break;
    case BuiltinOperator_RESHAPE:
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 1;
      break;
    case BuiltinOperator_RESIZE_BILINEAR:
    case BuiltinOperator_RESIZE_NEAREST_NEIGHBOR:
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 2;
      break;
    case BuiltinOperator_SHAPE:
      property.inputs = {{0, {}}};
      // Shape has no quantizable output.
      property.version = 1;
      break;
    case BuiltinOperator_SLICE:
      // We skip inputs 1 and 2 since they aren't real valued (they are the
      // index and size).
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 2;
      break;
    case BuiltinOperator_SQUEEZE:
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 1;
      break;
    case BuiltinOperator_SOFTMAX: {
      property.inputs = {{0, {}}};
      // Softmax requires output with 1/256 as scale and -128 as zero point.
      TensorProperty tensor_property;
      tensor_property.restriction = true;
      tensor_property.restricted_value = {1 / 256.0, -128};
      property.outputs = {{0, tensor_property}};
      property.version = 2;
      break;
    }
    case BuiltinOperator_STRIDED_SLICE:
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 2;
      break;
    case BuiltinOperator_SUB:
      property.inputs = {{0, {}}, {1, {}}};
      property.outputs = {{0, {}}};
      property.version = 2;
      break;
    case BuiltinOperator_SUM:
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.version = 2;
      break;
    case BuiltinOperator_TANH: {
      property.inputs = {{0, {}}};
      // Tanh requires output with 1/128 as scale and 0 as zero point.
      TensorProperty tensor_property;
      tensor_property.restriction = true;
      tensor_property.restricted_value = {1 / 128.0, 0};
      property.outputs = {{0, tensor_property}};
      property.version = 2;
      break;
    }
    case BuiltinOperator_TRANSPOSE:
      property.inputs = {{0, {}}};
      property.outputs = {{0, {}}};
      property.restrict_same_input_output_scale = true;
      property.version = 2;
      break;
    case BuiltinOperator_UNPACK:
      property.inputs = {{0, {}}};
      property.arbitrary_outputs = true;
      property.restrict_same_input_output_scale = true;
      property.version = 1;
      break;
    default:
      // No quantized implementation exists for this operation.
      property.quantizable = false;
  }
  return property;
}

}  // namespace operator_property
}  // namespace optimize
}  // namespace tflite
<|endoftext|>


<commit_before><commit_msg>Don't shutdown fontconfig.<commit_after><|endoftext|>


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

#include <qt/tonalutils.h>

#include <QFont>
#include <QFontMetrics>
#include <QRegExp>
#include <QRegExpValidator>
#include <QString>

bool TonalUtils::Supported()
{
    QFontMetrics fm = QFontMetrics(QFont());
    return fm.inFont(0xe9d9);
}

static QRegExpValidator tv(QRegExp("-?(?:[\\d\\xe9d9-\\xe9df]+\\.?|[\\d\\xe9d9-\\xe9df]*\\.[\\d\\xe9d9-\\xe9df]*)"), NULL);

QValidator::State TonalUtils::validate(QString&input, int&pos)
{
    return tv.validate(input, pos);
}

void TonalUtils::ConvertFromHex(QString&str)
{
    for (int i = 0; i < str.size(); ++i)
    {
        ushort c = str[i].unicode();
        if (c == '9')
            str[i] = 0xe9d9;
        else
        if (c >= 'A' && c <= 'F')
            str[i] = c + 0xe999;
        else
        if (c >= 'a' && c <= 'f')
            str[i] = c + 0xe979;
    }
}

void TonalUtils::ConvertToHex(QString&str)
{
    for (int i = 0; i < str.size(); ++i)
    {
        ushort c = str[i].unicode();
        if (c == 0xe9d9)
            str[i] = '9';
        else
        if (c == '9')
            str[i] = 'a';
        else
        if (c >= 0xe9da && c <= 0xe9df)
            str[i] = c - 0xe999;
    }
}
<commit_msg>GUI/tonalutils: For Tonal support detection, check that the font has all glyphs and they all have the same sizes<commit_after>// Copyright (c) 2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <qt/tonalutils.h>

#include <QFont>
#include <QFontMetrics>
#include <QRegExp>
#include <QRegExpValidator>
#include <QString>

static const QList<QChar> tonal_digits{0xe9df, 0xe9de, 0xe9dd, 0xe9dc, 0xe9db, 0xe9da, 0xe9d9, '8', '7', '6', '5', '4', '3', '2', '1', '0'};

namespace {

bool font_supports_tonal(const QFont& font)
{
    const QFontMetrics fm(font);
    QString s = "000";
    const QSize sz = fm.size(0, s);
    for (const auto& c : tonal_digits) {
        if (!fm.inFont(c)) return false;
        if (sz != fm.size(0, s)) return false;
    }
    return true;
}

} // anon namespace

bool TonalUtils::Supported()
{
    QFont default_font;
    if (font_supports_tonal(default_font)) return true;
    QFont last_resort_font(default_font.lastResortFamily());
    if (font_supports_tonal(last_resort_font)) return true;
    return false;
}

static QRegExpValidator tv(QRegExp("-?(?:[\\d\\xe9d9-\\xe9df]+\\.?|[\\d\\xe9d9-\\xe9df]*\\.[\\d\\xe9d9-\\xe9df]*)"), NULL);

QValidator::State TonalUtils::validate(QString&input, int&pos)
{
    return tv.validate(input, pos);
}

void TonalUtils::ConvertFromHex(QString&str)
{
    for (int i = 0; i < str.size(); ++i)
    {
        ushort c = str[i].unicode();
        if (c == '9')
            str[i] = 0xe9d9;
        else
        if (c >= 'A' && c <= 'F')
            str[i] = c + 0xe999;
        else
        if (c >= 'a' && c <= 'f')
            str[i] = c + 0xe979;
    }
}

void TonalUtils::ConvertToHex(QString&str)
{
    for (int i = 0; i < str.size(); ++i)
    {
        ushort c = str[i].unicode();
        if (c == 0xe9d9)
            str[i] = '9';
        else
        if (c == '9')
            str[i] = 'a';
        else
        if (c >= 0xe9da && c <= 0xe9df)
            str[i] = c - 0xe999;
    }
}
<|endoftext|>