<commit_before>#include "test_helper.h"
#include "uTensor/loaders/tensorIdxImporter.hpp"
#include "uTensor/ops/ArrayOps.hpp"

#include <iostream>
using std::cout;
using std::endl;

TensorIdxImporter t_import;
Context ctx;

// Default to using GTest like asserts and expects as these give more info that unity
// We will forward these commands to unity in test_helper.h
void test_operators_quantizeV2(){
    S_TENSOR b_q_ref = ctx.addCached(hold(t_import.float_import ("/fs/constants/qB/in/Cast_1_0.idx")), "b_q_ref");
    S_TENSOR b_min_q_ref = ctx.addCached(hold(t_import.float_import("/fs/constants/qB/in/Min_1_0.idx")), "b_min_q_ref");
    S_TENSOR b_max_q_ref = ctx.addCached(hold(t_import.float_import("/fs/constants/qB/in/Max_1_0.idx")), "b_max_q_ref");

    //reference outputs
    S_TENSOR ref_b_q = ctx.addCached(hold(t_import.ubyte_import("/fs/constants/qB/out/qB_0.idx")), "ref_b_q");
    S_TENSOR ref_b_min_q = ctx.addCached(hold(t_import.float_import("/fs/constants/qB/out/qB_1.idx")), "ref_b_min_q");
    S_TENSOR ref_b_max_q = ctx.addCached(hold(t_import.float_import("/fs/constants/qB/out/qB_2.idx")), "ref_b_max_q");

    S_TENSOR out_b_q = ctx.addCached(hold(new RamTensor<unsigned char>(b_q_ref->getShape())), "b_q");
    S_TENSOR out_b_min_q = ctx.addCached(hold(new RamTensor<float>(b_min_q_ref->getShape())), "b_min_q");
    S_TENSOR out_b_max_q = ctx.addCached(hold(new RamTensor<float>(b_max_q_ref->getShape())), "b_max_q");

    //Implementation goes here
    ctx.push_static(hold(new QuantizeV2Op()), "QuantizeV2Op", {"b_q_ref", "b_min_q_ref", "b_max_q_ref"}, {"b_q", "b_min_q", "b_max_q"});
    ctx.eval();

    double result = meanPercentErr<unsigned char>(ref_b_q.get(), out_b_q.get()) + meanPercentErr<float>(ref_b_min_q.get(), out_b_min_q.get()) + meanPercentErr<float>(ref_b_max_q.get(), out_b_max_q.get());
    EXPECT_EQ(result, 0);
}

void test_operators_dequantize(void) {

    //reference inputs
    S_TENSOR a = ctx.addCached(hold(t_import.ubyte_import("/fs/constants/deQ/in/rQ_0.idx")), "a");
    S_TENSOR a_min = ctx.addCached(hold(t_import.float_import("/fs/constants/deQ/in/rQ_1.idx")), "a_min");
    S_TENSOR a_max = ctx.addCached(hold(t_import.float_import("/fs/constants/deQ/in/rQ_2.idx")), "a_max");

    //reference outputs
    S_TENSOR out_ref = ctx.addCached(hold(t_import.float_import("/fs/constants/deQ/out/deQ_0.idx")), "out_ref");

    //modify the checks below:
    S_TENSOR out = ctx.addCached(hold(new RamTensor<float>(out_ref->getShape())), "out");

    ctx.push_static(hold(new DequantizeOp()), "DequantizeOp", {"a", "a_min", "a_max"}, {"out"});
    ctx.eval();

    double result = meanPercentErr<float>(out.get(), out_ref.get());
    EXPECT_EQ(result, 0);
}

void test_operators_reshape(void) {
    //reference inputs
    S_TENSOR ref_a = ctx.addCached(hold(t_import.float_import("/fs/constants/ref_reshape/in/Const_0.idx")), "ref_a");
    S_TENSOR ref_dim = ctx.addCached(hold(t_import.int_import("/fs/constants/ref_reshape/in/Const_1_0.idx")), "ref_dim");

    //reference outputs
    S_TENSOR out_ref_2 = ctx.addCached(hold(t_import.float_import("/fs/constants/ref_reshape/out/ref_reshape_0.idx")), "out_ref_2");

    //modify the checks below:
    S_TENSOR out_2 = ctx.addCached(hold(new RamTensor<float>(out_ref_2->getShape())), "out_2");

    ctx.push_static(hold(new ReshapeOp()), "ReshapeOp", {"ref_a", "ref_dim"}, {"out_2"});
    ctx.eval();

    double result = meanPercentErr<float>(out_2.get(), out_ref_2.get());
    EXPECT_EQ(result, 0);
}
// First configure the uTensor test runner
UTENSOR_TEST_CONFIGURE()

// Second declare tests to run
UTENSOR_TEST(operators, quantizeV2, "Quantize V2 test")
UTENSOR_TEST(operators, dequantize, "Dequantization Test")
UTENSOR_TEST(operators, reshape, "Reshape Test")

// Third, run like hell
UTENSOR_TEST_RUN()
<commit_msg>Add gather test<commit_after>#include "test_helper.h"
#include "uTensor/loaders/tensorIdxImporter.hpp"
#include "uTensor/ops/ArrayOps.hpp"

#include <iostream>
using std::cout;
using std::endl;

TensorIdxImporter t_import;
Context ctx;

// Default to using GTest like asserts and expects as these give more info that unity
// We will forward these commands to unity in test_helper.h
void test_operators_quantizeV2(){
    S_TENSOR b_q_ref = ctx.addCached(hold(t_import.float_import ("/fs/constants/qB/in/Cast_1_0.idx")), "b_q_ref");
    S_TENSOR b_min_q_ref = ctx.addCached(hold(t_import.float_import("/fs/constants/qB/in/Min_1_0.idx")), "b_min_q_ref");
    S_TENSOR b_max_q_ref = ctx.addCached(hold(t_import.float_import("/fs/constants/qB/in/Max_1_0.idx")), "b_max_q_ref");

    //reference outputs
    S_TENSOR ref_b_q = ctx.addCached(hold(t_import.ubyte_import("/fs/constants/qB/out/qB_0.idx")), "ref_b_q");
    S_TENSOR ref_b_min_q = ctx.addCached(hold(t_import.float_import("/fs/constants/qB/out/qB_1.idx")), "ref_b_min_q");
    S_TENSOR ref_b_max_q = ctx.addCached(hold(t_import.float_import("/fs/constants/qB/out/qB_2.idx")), "ref_b_max_q");

    S_TENSOR out_b_q = ctx.addCached(hold(new RamTensor<unsigned char>(b_q_ref->getShape())), "b_q");
    S_TENSOR out_b_min_q = ctx.addCached(hold(new RamTensor<float>(b_min_q_ref->getShape())), "b_min_q");
    S_TENSOR out_b_max_q = ctx.addCached(hold(new RamTensor<float>(b_max_q_ref->getShape())), "b_max_q");

    //Implementation goes here
    ctx.push_static(hold(new QuantizeV2Op()), "QuantizeV2Op", {"b_q_ref", "b_min_q_ref", "b_max_q_ref"}, {"b_q", "b_min_q", "b_max_q"});
    ctx.eval();

    double result = meanPercentErr<unsigned char>(ref_b_q.get(), out_b_q.get()) + meanPercentErr<float>(ref_b_min_q.get(), out_b_min_q.get()) + meanPercentErr<float>(ref_b_max_q.get(), out_b_max_q.get());
    EXPECT_EQ(result, 0);
}

void test_operators_dequantize(void) {

    //reference inputs
    S_TENSOR a = ctx.addCached(hold(t_import.ubyte_import("/fs/constants/deQ/in/rQ_0.idx")), "a");
    S_TENSOR a_min = ctx.addCached(hold(t_import.float_import("/fs/constants/deQ/in/rQ_1.idx")), "a_min");
    S_TENSOR a_max = ctx.addCached(hold(t_import.float_import("/fs/constants/deQ/in/rQ_2.idx")), "a_max");

    //reference outputs
    S_TENSOR out_ref = ctx.addCached(hold(t_import.float_import("/fs/constants/deQ/out/deQ_0.idx")), "out_ref");

    //modify the checks below:
    S_TENSOR out = ctx.addCached(hold(new RamTensor<float>(out_ref->getShape())), "out");

    ctx.push_static(hold(new DequantizeOp()), "DequantizeOp", {"a", "a_min", "a_max"}, {"out"});
    ctx.eval();

    double result = meanPercentErr<float>(out.get(), out_ref.get());
    EXPECT_EQ(result, 0);
}

void test_operators_reshape(void) {
    //reference inputs
    S_TENSOR ref_a = ctx.addCached(hold(t_import.float_import("/fs/constants/ref_reshape/in/Const_0.idx")), "ref_a");
    S_TENSOR ref_dim = ctx.addCached(hold(t_import.int_import("/fs/constants/ref_reshape/in/Const_1_0.idx")), "ref_dim");

    //reference outputs
    S_TENSOR out_ref_2 = ctx.addCached(hold(t_import.float_import("/fs/constants/ref_reshape/out/ref_reshape_0.idx")), "out_ref_2");

    //modify the checks below:
    S_TENSOR out_2 = ctx.addCached(hold(new RamTensor<float>(out_ref_2->getShape())), "out_2");

    ctx.push_static(hold(new ReshapeOp()), "ReshapeOp", {"ref_a", "ref_dim"}, {"out_2"});
    ctx.eval();

    double result = meanPercentErr<float>(out_2.get(), out_ref_2.get());
    EXPECT_EQ(result, 0);
}

void test_operators_gather(void) {
    Tensor* input = new RamTensor<float>();
    Tensor* output = new RamTensor<float>();
    Tensor* out_ref = new RamTensor<float>();
    Tensor* indices  = new RamTensor<uint32_t>();
    TensorShape tmp({2, 2});
    TensorShape tmp2({3});

    input->init(tmp);
    output->init(tmp2);
    indices->init(tmp2);
    out_ref->init(tmp2);

    input->write<float>(0,0)[0] = 100.0;
    input->write<float>(0,0)[1] = 11.0;
    input->write<float>(0,0)[2] = 12.0;
    input->write<float>(0,0)[3] = 13.0;

    indices->write<uint32_t>(0,0)[0] = 1;
    indices->write<uint32_t>(0,0)[1] = 2;
    indices->write<uint32_t>(0,0)[2] = 1;

    out_ref->write<float>(0,0)[0] = 11.0;
    out_ref->write<float>(0,0)[1] = 12.0;
    out_ref->write<float>(0,0)[2] = 11.0;

    ctx.add(input, "g_input");
    ctx.add(output, "g_output");
    ctx.add(indices, "g_indices");

    ctx.push(new GatherOp<float>(),
            {"g_input", "g_indices"},
            {"g_output"});
    ctx.eval();

    double result = meanPercentErr<float>(output, out_ref);
    EXPECT_EQ(result, 0);

}
// First configure the uTensor test runner
UTENSOR_TEST_CONFIGURE()

// Second declare tests to run
UTENSOR_TEST(operators, quantizeV2, "Quantize V2 test")
UTENSOR_TEST(operators, dequantize, "Dequantization Test")
UTENSOR_TEST(operators, reshape, "Reshape Test")

// Third, run like hell
UTENSOR_TEST_RUN()
<|endoftext|>


<commit_before>#include <chrono>
#include <iostream>
#include <fstream>
#include <numeric>
#include <math.h>
#include <string>
#include <time.h>
#include "mkldnn.hpp"
#include "configure.h"

using namespace mkldnn;
using namespace std;

void maxpool()
{
    auto cpu_engine = engine(engine::cpu, 0);
    std::vector<float> net_src(BATCH_SIZE * FIn * N * N);
    std::vector<float> net_dst(BATCH_SIZE * FIn * ((N - K_Y + 2 * P_Y) / S_Y + 1) * ((N - K_X + 2 * P_X) / S_X + 1));

    /* Initializing non-zero values for src */
    srand(1);
    for (size_t i = 0; i < net_src.size(); ++i)
        net_src[i] = rand() % 10;

    memory::dims src_tz = {BATCH_SIZE, FIn, N, N};

    /* Create memory for user data */
    auto user_src_memory = memory(
        {{{src_tz}, memory::data_type::f32, memory::format::nchw},
         cpu_engine},
        net_src.data());

    /* Create mmemory descriptors for source data */
    auto src_md = memory::desc({src_tz}, memory::data_type::f32,
                               memory::format::nchw);

    /* Pool */
    memory::dims pool_dst_tz = {BATCH_SIZE, FIn, ((N - K_Y + 2 * P_Y) / S_Y + 1), ((N - K_X + 2 * P_X) / S_X + 1)};
    memory::dims pool_kernel = {K_Y, K_X};
    memory::dims pool_strides = {S_Y, S_X};
    auto pool_padding = {P_Y, P_X};

    /* Create memory for pool dst data in user format */
    auto pool_user_dst_memory = memory(
        {{{pool_dst_tz}, memory::data_type::f32, memory::format::nchw},
         cpu_engine},
        net_dst.data());

    /* Create pool dst memory descriptor in format any */
    auto pool_dst_md = memory::desc({pool_dst_tz}, memory::data_type::f32,
                                    memory::format::any);

    /* Create a pooling primitive descriptor */
    auto pool_desc = pooling_forward::desc(
        prop_kind::forward, pooling_max,
        src_md, pool_dst_md,
        pool_strides, pool_kernel, pool_padding, pool_padding,
        padding_kind::zero);
    auto pool_pd = pooling_forward::primitive_desc(pool_desc, cpu_engine);

    /* Create reorder primitive between pool dst and user dst format if needed */
    auto pool_dst_memory = pool_user_dst_memory;
    bool reorder_pool_dst = false;
    primitive pool_reorder_dst;
    if (memory::primitive_desc(pool_pd.dst_primitive_desc()) != pool_user_dst_memory.get_primitive_desc())
    {
        pool_dst_memory = memory(pool_pd.dst_primitive_desc());
        pool_reorder_dst = reorder(pool_dst_memory, pool_user_dst_memory);
        reorder_pool_dst = true;
    }

    /* Create pooling workspace memory if training */
    auto pool_workspace_memory = memory(pool_pd.workspace_primitive_desc());

    /* Finally create a pooling primitive */
    auto pool = pooling_forward(pool_pd, user_src_memory, pool_dst_memory,
                                pool_workspace_memory);

    /* Build forward net */
    std::vector<primitive> net_fwd;
    net_fwd.push_back(pool);
    if (reorder_pool_dst)
        net_fwd.push_back(pool_reorder_dst);

    std::vector<std::chrono::duration<double, std::milli>> duration_vector_2;
    for (int i = 0; i < NB_TESTS; i++)
    {
        auto start1 = std::chrono::high_resolution_clock::now();
        stream(stream::kind::eager).submit(net_fwd).wait();
        auto end1 = std::chrono::high_resolution_clock::now();
        std::chrono::duration<double, std::milli> duration = end1 - start1;
        duration_vector_2.push_back(duration);
    }
    std::cout << "\t\tMKL-DNN maxpool duration"
              << ": " << median(duration_vector_2) << "; " << std::endl;

    printf("writing result in file\n");
    ofstream resultfile;
    resultfile.open("mkldnn_result.txt");

    float *poolres = (float *)pool_dst_memory.get_data_handle();
    for (size_t i = 0; i < BATCH_SIZE; ++i)
        for (size_t j = 0; j < FIn; ++j)
            for (size_t k = 0; k < ((N - K_Y + 2 * P_Y) / S_Y + 1); ++k)
                for (size_t l = 0; l < ((N - K_X + 2 * P_X) / S_X + 1); ++l)
                    resultfile << poolres[i * FIn * ((N - K_Y + 2 * P_Y) / S_Y + 1) * ((N - K_X + 2 * P_X) / S_X + 1) + j * ((N - K_Y + 2 * P_Y) / S_Y + 1) * ((N - K_X + 2 * P_X) / S_X + 1) + k * ((N - K_X + 2 * P_X) / S_X + 1) + l];
    resultfile.close();
}

int main(int argc, char **argv)
{
    try
    {
        maxpool();
    }
    catch (error &e)
    {
        std::cerr << "status: " << e.status << std::endl;
        std::cerr << "message: " << e.message << std::endl;
    }
    return 0;
}
<commit_msg>Delete maxpool_layer_generator_mkldnn.cpp<commit_after><|endoftext|>


<commit_before>#include "twitchuser.h"

namespace chatterino {
namespace twitch {
TwitchUser::TwitchUser(const QString &username, const QString &oauthToken,
                       const QString &oauthClient)
    : IrcUser2(username, username, username, "oauth:" + oauthToken)
{
    _oauthClient = oauthClient;
    _oauthToken = oauthToken;
}

const QString &TwitchUser::getOAuthClient() const
{
    return _oauthClient;
}

const QString &TwitchUser::getOAuthToken() const
{
    return _oauthToken;
}

bool TwitchUser::isAnon() const
{
    return IrcUser2::getNickName().startsWith("justinfan");
}
}
}
<commit_msg>moved stuff to the thing where it should be<commit_after>#include "twitchuser.h"

namespace chatterino {
namespace twitch {
TwitchUser::TwitchUser(const QString &username, const QString &oauthToken,
                       const QString &oauthClient)
    : IrcUser2(username, username, username, "oauth:" + oauthToken)
    , _oauthClient(oauthClient)
    , _oauthToken(oauthToken)
{
}

const QString &TwitchUser::getOAuthClient() const
{
    return _oauthClient;
}

const QString &TwitchUser::getOAuthToken() const
{
    return _oauthToken;
}

bool TwitchUser::isAnon() const
{
    return IrcUser2::getNickName().startsWith("justinfan");
}
}
}
<|endoftext|>


<commit_before>/*
** network-thread.cpp
** Login : <hcuche@hcuche-de>
** Started on  Tue Jan 10 11:41:39 2012 Herve Cuche
** $Id$
**
** Author(s):
**  - Herve Cuche <hcuche@aldebaran-robotics.com>
**
** Copyright (C) 2012 Herve Cuche
*/

#include <iostream>

#include <qi/log.hpp>

#include <qimessaging/transport/network_thread.hpp>

namespace qi {

static void errorcb(struct bufferevent *bev,
                    short error,
                    void *ctx)
{
  if (error & BEV_EVENT_EOF)
  {
    // connection has been closed, do any clean up here
    qiLogError("qimessaging.TransportSocket") << "connection has been closed, do any clean up here" << std::endl;
  }
  else if (error & BEV_EVENT_ERROR)
  {
    // check errno to see what error occurred
    qiLogError("qimessaging.TransportSocket")  << "check errno to see what error occurred" << std::endl;
  }
  else if (error & BEV_EVENT_TIMEOUT)
  {
    // must be a timeout event handle, handle it
    qiLogError("qimessaging.TransportSocket")  << "must be a timeout event handle, handle it" << std::endl;
  }
}

NetworkThread::NetworkThread()
{
  if (!(_base = event_base_new()))
    return;
  _thd = boost::thread(&NetworkThread::run, this);
}

NetworkThread::~NetworkThread()
{
  event_base_free(_base);
}

void NetworkThread::run()
{

  struct bufferevent *bev = bufferevent_socket_new(_base, -1, BEV_OPT_CLOSE_ON_FREE);
  bufferevent_setcb(bev, NULL, NULL, ::qi::errorcb, this);
  bufferevent_enable(bev, EV_READ|EV_WRITE);

  event_base_dispatch(_base);
}

struct event_base* NetworkThread::getEventBase()
{
  return _base;
}

}
<commit_msg>Dubious commit: WSASTARTUP and WSACLEANUP<commit_after>/*
** network-thread.cpp
** Login : <hcuche@hcuche-de>
** Started on  Tue Jan 10 11:41:39 2012 Herve Cuche
** $Id$
**
** Author(s):
**  - Herve Cuche <hcuche@aldebaran-robotics.com>
**
** Copyright (C) 2012 Herve Cuche
*/

#include <iostream>

#include <qi/log.hpp>

#include <qimessaging/transport/network_thread.hpp>

namespace qi {

static void errorcb(struct bufferevent *bev,
                    short error,
                    void *ctx)
{
  if (error & BEV_EVENT_EOF)
  {
    // connection has been closed, do any clean up here
    qiLogError("qimessaging.TransportSocket") << "connection has been closed, do any clean up here" << std::endl;
  }
  else if (error & BEV_EVENT_ERROR)
  {
    // check errno to see what error occurred
    qiLogError("qimessaging.TransportSocket")  << "check errno to see what error occurred" << std::endl;
  }
  else if (error & BEV_EVENT_TIMEOUT)
  {
    // must be a timeout event handle, handle it
    qiLogError("qimessaging.TransportSocket")  << "must be a timeout event handle, handle it" << std::endl;
  }
}

NetworkThread::NetworkThread()
{
#ifdef _WIN32
  // libevent does not call WSAStartup
  WSADATA WSAData;
  // TODO: handle return code
  ::WSAStartup(MAKEWORD(1, 0), &WSAData);
#endif

  if (!(_base = event_base_new()))
    return;
  _thd = boost::thread(&NetworkThread::run, this);
}

NetworkThread::~NetworkThread()
{
  event_base_free(_base);
#ifdef _WIN32
  // TODO handle return code
  ::WSACleanup();
#endif
}

void NetworkThread::run()
{

  struct bufferevent *bev = bufferevent_socket_new(_base, -1, BEV_OPT_CLOSE_ON_FREE);
  bufferevent_setcb(bev, NULL, NULL, ::qi::errorcb, this);
  bufferevent_enable(bev, EV_READ|EV_WRITE);

  event_base_dispatch(_base);
}

struct event_base* NetworkThread::getEventBase()
{
  return _base;
}

}
<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (c) 2012-2019 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * 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 OWNER 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.
 *
 ****************************************************************************/

/**
 * @file Subscription.hpp
 *
 */

#pragma once

#include <uORB/uORB.h>
#include <px4_defines.h>

#include "uORBDeviceNode.hpp"
#include "uORBManager.hpp"
#include "uORBUtils.hpp"

namespace uORB
{

// Base subscription wrapper class
class Subscription
{
public:

	/**
	 * Constructor
	 *
	 * @param meta The uORB metadata (usually from the ORB_ID() macro) for the topic.
	 * @param instance The instance for multi sub.
	 */
	Subscription(const orb_metadata *meta, uint8_t instance = 0) : _meta(meta), _instance(instance)
	{
		init();
	}

	virtual ~Subscription() { unsubscribe(); }

	bool init();
	bool forceInit();

	bool valid() const { return _node != nullptr; }
	bool published() { return valid() ? _node->is_published() : init(); }

	/**
	 * Check if there is a new update.
	 * */
	virtual bool updated() { return published() ? (_node->published_message_count() != _last_generation) : false; }

	/**
	 * Update the struct
	 * @param data The uORB message struct we are updating.
	 */
	virtual bool update(void *dst) { return updated() ? copy(dst) : false; }

	/**
	 * Check if subscription updated based on timestamp.
	 *
	 * @return true only if topic was updated based on a timestamp and
	 * copied to buffer successfully.
	 * If topic was not updated since last check it will return false but
	 * still copy the data.
	 * If no data available data buffer will be filled with zeros.
	 */
	bool update(uint64_t *time, void *dst);

	/**
	 * Copy the struct
	 * @param data The uORB message struct we are updating.
	 */
	bool copy(void *dst) { return published() ? _node->copy(dst, _last_generation) : false; }

	hrt_abstime	last_update() { return published() ? _node->last_update() : 0; }

	uint8_t		get_instance() const { return _instance; }
	orb_id_t	get_topic() const { return _meta; }

protected:

	bool subscribe();
	void unsubscribe();

	DeviceNode		*_node{nullptr};
	const orb_metadata	*_meta{nullptr};

	/**
	 * Subscription's latest data generation.
	 * Also used to track (and rate limit) subscription
	 * attempts if the topic has not yet been published.
	 */
	unsigned		_last_generation{0};
	uint8_t			_instance{0};
};

// Subscription wrapper class with configured interval
class SubscriptionInterval : public Subscription
{
public:
	/**
	 * Constructor
	 *
	 * @param meta The uORB metadata (usually from the ORB_ID() macro) for the topic.
	 * @param interval  The minimum interval in milliseconds between updates
	 * @param instance The instance for multi sub.
	 */
	SubscriptionInterval(const orb_metadata *meta, unsigned interval = 0, uint8_t instance = 0) :
		Subscription(meta, instance),
		_interval(interval)
	{}

	virtual ~SubscriptionInterval() = default;

	bool updated() override
	{
		if (hrt_elapsed_time(&_last_update) >= (_interval * 1000)) {
			return Subscription::updated();
		}

		return false;
	}

	bool update(void *dst) override
	{
		if (updated()) {
			if (copy(dst)) {
				_last_update = hrt_absolute_time();
				return true;
			}
		}

		return false;
	}

	int get_interval() const { return _interval; }
	void set_interval(unsigned interval) { _interval = interval; }

protected:
	uint64_t _last_update{0};	// last update in microseconds
	unsigned _interval{0};		// interval in milliseconds
};

// Subscription wrapper class with data
template<class T>
class SubscriptionData : public Subscription
{
public:
	/**
	 * Constructor
	 *
	 * @param meta The uORB metadata (usually from the ORB_ID() macro) for the topic.
	 * @param instance The instance for multi sub.
	 */
	SubscriptionData(const orb_metadata *meta, uint8_t instance = 0) :
		Subscription(meta, instance)
	{
		copy(&_data);
	}

	virtual ~SubscriptionData() = default;

	// no copy, assignment, move, move assignment
	SubscriptionData(const SubscriptionData &) = delete;
	SubscriptionData &operator=(const SubscriptionData &) = delete;
	SubscriptionData(SubscriptionData &&) = delete;
	SubscriptionData &operator=(SubscriptionData &&) = delete;

	// update the embedded struct.
	bool update() { return Subscription::update((void *)(&_data)); }

	const T &get() const { return _data; }

private:

	T _data{};
};

// Subscription wrapper class with data and configured interval
template<class T>
class SubscriptionIntervalData : public SubscriptionInterval
{
public:
	/**
	 * Constructor
	 *
	 * @param meta The uORB metadata (usually from the ORB_ID() macro) for the topic.
	 * @param interval  The minimum interval in milliseconds between updates
	 * @param instance The instance for multi sub.
	 */
	SubscriptionIntervalData(const orb_metadata *meta, unsigned interval = 0, uint8_t instance = 0) :
		SubscriptionInterval(meta, interval, instance)
	{
		copy(&_data);
	}

	~SubscriptionIntervalData() override = default;

	// no copy, assignment, move, move assignment
	SubscriptionIntervalData(const SubscriptionIntervalData &) = delete;
	SubscriptionIntervalData &operator=(const SubscriptionIntervalData &) = delete;
	SubscriptionIntervalData(SubscriptionIntervalData &&) = delete;
	SubscriptionIntervalData &operator=(SubscriptionIntervalData &&) = delete;

	// update the embedded struct.
	bool update() { return SubscriptionInterval::update((void *)(&_data)); }

	const T &get() const { return _data; }

private:
	T _data{};
};

} // namespace uORB
<commit_msg>uORB remove unused SubscriptionInterval and SubscriptionIntervalData<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2012-2019 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * 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 OWNER 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.
 *
 ****************************************************************************/

/**
 * @file Subscription.hpp
 *
 */

#pragma once

#include <uORB/uORB.h>
#include <px4_defines.h>

#include "uORBDeviceNode.hpp"
#include "uORBManager.hpp"
#include "uORBUtils.hpp"

namespace uORB
{

// Base subscription wrapper class
class Subscription
{
public:

	/**
	 * Constructor
	 *
	 * @param meta The uORB metadata (usually from the ORB_ID() macro) for the topic.
	 * @param instance The instance for multi sub.
	 */
	Subscription(const orb_metadata *meta, uint8_t instance = 0) : _meta(meta), _instance(instance)
	{
		init();
	}

	~Subscription() { unsubscribe(); }

	bool init();
	bool forceInit();

	bool valid() const { return _node != nullptr; }
	bool published() { return valid() ? _node->is_published() : init(); }

	/**
	 * Check if there is a new update.
	 * */
	bool updated() { return published() ? (_node->published_message_count() != _last_generation) : false; }

	/**
	 * Update the struct
	 * @param data The uORB message struct we are updating.
	 */
	bool update(void *dst) { return updated() ? copy(dst) : false; }

	/**
	 * Check if subscription updated based on timestamp.
	 *
	 * @return true only if topic was updated based on a timestamp and
	 * copied to buffer successfully.
	 * If topic was not updated since last check it will return false but
	 * still copy the data.
	 * If no data available data buffer will be filled with zeros.
	 */
	bool update(uint64_t *time, void *dst);

	/**
	 * Copy the struct
	 * @param data The uORB message struct we are updating.
	 */
	bool copy(void *dst) { return published() ? _node->copy(dst, _last_generation) : false; }

	hrt_abstime	last_update() { return published() ? _node->last_update() : 0; }

	uint8_t		get_instance() const { return _instance; }
	orb_id_t	get_topic() const { return _meta; }

protected:

	bool subscribe();
	void unsubscribe();

	DeviceNode		*_node{nullptr};
	const orb_metadata	*_meta{nullptr};

	/**
	 * Subscription's latest data generation.
	 * Also used to track (and rate limit) subscription
	 * attempts if the topic has not yet been published.
	 */
	unsigned		_last_generation{0};
	uint8_t			_instance{0};
};

// Subscription wrapper class with data
template<class T>
class SubscriptionData : public Subscription
{
public:
	/**
	 * Constructor
	 *
	 * @param meta The uORB metadata (usually from the ORB_ID() macro) for the topic.
	 * @param instance The instance for multi sub.
	 */
	SubscriptionData(const orb_metadata *meta, uint8_t instance = 0) :
		Subscription(meta, instance)
	{
		copy(&_data);
	}

	~SubscriptionData() = default;

	// no copy, assignment, move, move assignment
	SubscriptionData(const SubscriptionData &) = delete;
	SubscriptionData &operator=(const SubscriptionData &) = delete;
	SubscriptionData(SubscriptionData &&) = delete;
	SubscriptionData &operator=(SubscriptionData &&) = delete;

	// update the embedded struct.
	bool update() { return Subscription::update((void *)(&_data)); }

	const T &get() const { return _data; }

private:

	T _data{};
};

} // namespace uORB
<|endoftext|>


<commit_before>//*****************************************************************************
// Copyright 2017-2019 Intel Corporation
//
// 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 <algorithm>
#include <iostream>
#include <regex>
#include <unordered_set>
#include <vector>

#include "graph_rewrite.hpp"
#include "ngraph/log.hpp"

using namespace std;
using namespace ngraph;

// GraphRewrite algorithm:
// GraphRewrite processes an input graph in an topological order(i.e. args before users)
// Given the following graph:          Abs2
//                                   /       \
//                         Constant1         Add4 - Result5
//                                   \      /
//                                    Neg3
//
// The topological order would be : `Constant1`, `Abs2`, `Neg3`, `Add4`, `Result5`
// Note, `Abs2` comes before `Neg3` as `Abs2`'s id = 2 is *less* than `Neg3`'s one (id = 3)
// Next, GraphRewrite will invoke matchers registered in an order registered in a c-tor
// i.e. if a c-tor calls `construct_m1()`; `construct_m2()`; `construct_m3()`;
// Matchers will be called as follows: `m1`, `m2`, `m3`
// Matchers should only replace nodes in the graph that come before the current root
// node in the topological order. For example, if Matcher matches Neg3, it should only
// replace nodes `Abs2` and `Constant1` if needed
// This gives Matchers a nice cascading property. For example, if m1 folds `Abs2(Constant1)`
// and `m2` folds `Neg3(Constant1)` when `m3` is called on `Add4` it will discover that
// both `Abs2` and `Neg3` were already replaced by constants, so `Add4` will also be folded into one.
// If any Matcher succeeds the rest of the matchers will **not** be called.
// E.g. if `m1` succeeds and replaces `Abs2` with a new constant, nor `m2` or `m3` will be called
// However, sometimes, you will need more than one fusion occur on the same node.
// In this case, you should be able to request another pass of GraphRewrite.
// To request another pass, you will need to register fusions in a callback:
// i.e. you will need to pass `this` into a callback and then call `this->construct_X`
// This will schedule another pass of GraphRewrite with the following fusion.
// This approach should only be used if you are either:
// a) need more than one fusion occur on the same node
// b) you are modifying nodes after the current node in the topological order
// c) there's no linear order of fusions which will give
//    the correct final fusion. i.e. the same fusion needs to occur before and after some other fusion

bool pass::GraphRewrite::run_on_function(shared_ptr<Function> f)
{
    bool rewritten = false;
    const size_t NUM_TRIES = 10;
    size_t tries = NUM_TRIES;
    vector<MatchClosure> original_matchers{m_matchers};
    bool is_dyn_func = f->is_dynamic();
    do
    {
        rewritten = false;
        // m_matchers may contain newly constructed matchers for matchers
        // that need multiple passes. See comments above.
        vector<MatchClosure> matchers_to_run{m_matchers};
        m_matchers.clear();
        for (auto node : f->get_ordered_ops())
        {
            for (auto& closure : matchers_to_run)
            {
                if (is_dyn_func && closure.property[PassProperty::REQUIRE_STATIC_SHAPE])
                {
                    NGRAPH_DEBUG << "matcher callback requires static shape but the "
                                    "function is dynamic, skipping this "
                                    "optimization till the shapes are fully "
                                    "materialized";
                    continue;
                }
                NGRAPH_DEBUG << "Running matcher " << closure.matcher->get_name() << "("
                             << closure.matcher->get_pattern()->get_name() << ") on "
                             << node->get_name();
                if (closure.matcher->match(node))
                {
                    NGRAPH_DEBUG << "Matcher " << closure.matcher << closure.matcher->get_name()
                                 << " matched " << node->get_name();
                    if (closure.callback(*closure.matcher.get()))
                    {
                        rewritten = true;
                        // If call back may change function's is_dynamic state, we need to
                        // update the cached value.
                        if (closure.property.is_set(PassProperty::CHANGE_DYNAMIC_STATE))
                        {
                            is_dyn_func = f->is_dynamic();
                        }
                        break;
                    }
                }
            }
        }

    } while (rewritten && m_matchers.size() > 0 && tries--);

    m_matchers.assign(original_matchers.begin(), original_matchers.end());
    return (NUM_TRIES - tries) > 1; //this means a graph was transformed
}

static vector<regex> initialize_fusion_regexes()
{
    const char* cnsf = getenv("NGRAPH_DISABLED_FUSIONS");
    vector<regex> regexes;
    if (cnsf)
    {
        const string nsf = cnsf;
        const auto sregexes = split(nsf, ';');

        transform(sregexes.begin(),
                  sregexes.end(),
                  back_inserter(regexes),
                  [](const string& c) -> regex { return regex(c); });
    }
    return regexes;
}

bool pass::GraphRewrite::is_enabled(const shared_ptr<pattern::Matcher>& m) const
{
    //note, regexes are static to avoid re-initialization
    static const auto regexes = initialize_fusion_regexes();

    for (const auto& regex : regexes)
    {
        if (regex_match(m->get_name(), regex))
        {
            NGRAPH_DEBUG << "Disabling matcher " << m->get_name();
            return false;
        }
    }

    return true;
}

void pass::GraphRewrite::add_matcher(const shared_ptr<pattern::Matcher>& m,
                                     const graph_rewrite_callback& callback,
                                     const PassPropertyMask& property)
{
    if (is_enabled(m))
    {
        m_matchers.push_back({m, callback, property});
        // If any matcher call back may change dynamic state, we need to
        // update the pass property.
        if (property.is_set(PassProperty::CHANGE_DYNAMIC_STATE))
        {
            set_property(PassProperty::CHANGE_DYNAMIC_STATE, true);
        }
    }
}

void pass::GraphRewrite::add_matcher(const shared_ptr<pattern::Matcher>& m,
                                     const graph_rewrite_callback& callback)
{
    // TODO: before deprecate this function, by default expect the
    // callback require static shape.
    add_matcher(m, callback, {PassProperty::REQUIRE_STATIC_SHAPE});
}

void pass::RecurrentGraphRewrite::add_matcher(
    const std::shared_ptr<pattern::RecurrentMatcher>& m,
    const ngraph::recurrent_graph_rewrite_callback& callback,
    const PassPropertyMask& property)
{
    m_matchers.push_back({m, callback, property});
    // If any matcher call back may change dynamic state, we need to
    // update the pass property.
    if (property.is_set(PassProperty::CHANGE_DYNAMIC_STATE))
    {
        set_property(PassProperty::CHANGE_DYNAMIC_STATE, true);
    }
}

void pass::RecurrentGraphRewrite::add_matcher(
    const std::shared_ptr<pattern::RecurrentMatcher>& m,
    const ngraph::recurrent_graph_rewrite_callback& callback)
{
    // TODO: before deprecate this function, by default expect the
    // callback require static shape.
    add_matcher(m, callback, {PassProperty::REQUIRE_STATIC_SHAPE});
}

bool pass::RecurrentGraphRewrite::run_on_function(shared_ptr<Function> f)
{
    bool changed = false;
    size_t i = 0;

    auto run_matchers = [&]() -> bool {
        bool is_dyn_func = f->is_dynamic();
        for (auto node : f->get_ops())
        {
            for (auto& closure : m_matchers)
            {
                if (is_dyn_func && closure.property[PassProperty::REQUIRE_STATIC_SHAPE])
                {
                    NGRAPH_DEBUG << "matcher callback requires static shape but the "
                                    "function is dynamic, skipping this "
                                    "optimization till the shapes are fully "
                                    "materialized";
                    continue;
                }
                NGRAPH_DEBUG << "Running matcher " << closure.matcher << " on " << node->get_name();
                if (closure.matcher->match(node))
                {
                    NGRAPH_DEBUG << "Matcher " << closure.matcher << " matched "
                                 << node->get_name();
                    if (closure.callback(*closure.matcher.get()))
                    {
                        // If call back may change function's is_dynamic state, we need to
                        // update the cached value.
                        if (closure.property.is_set(PassProperty::CHANGE_DYNAMIC_STATE))
                        {
                            is_dyn_func = f->is_dynamic();
                        }
                        return true;
                    }
                }
            }
        }
        return false;
    };

    do
    {
        changed = run_matchers();
        i++;
    } while (changed && i < m_num_iters);
    return changed;
}
<commit_msg>Backport fix from #2973 (#2976)<commit_after>//*****************************************************************************
// Copyright 2017-2019 Intel Corporation
//
// 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 <algorithm>
#include <iostream>
#include <regex>
#include <unordered_set>
#include <vector>

#include "graph_rewrite.hpp"
#include "ngraph/log.hpp"

using namespace std;
using namespace ngraph;

// GraphRewrite algorithm:
// GraphRewrite processes an input graph in an topological order(i.e. args before users)
// Given the following graph:          Abs2
//                                   /       \
//                         Constant1         Add4 - Result5
//                                   \      /
//                                    Neg3
//
// The topological order would be : `Constant1`, `Abs2`, `Neg3`, `Add4`, `Result5`
// Note, `Abs2` comes before `Neg3` as `Abs2`'s id = 2 is *less* than `Neg3`'s one (id = 3)
// Next, GraphRewrite will invoke matchers registered in an order registered in a c-tor
// i.e. if a c-tor calls `construct_m1()`; `construct_m2()`; `construct_m3()`;
// Matchers will be called as follows: `m1`, `m2`, `m3`
// Matchers should only replace nodes in the graph that come before the current root
// node in the topological order. For example, if Matcher matches Neg3, it should only
// replace nodes `Abs2` and `Constant1` if needed
// This gives Matchers a nice cascading property. For example, if m1 folds `Abs2(Constant1)`
// and `m2` folds `Neg3(Constant1)` when `m3` is called on `Add4` it will discover that
// both `Abs2` and `Neg3` were already replaced by constants, so `Add4` will also be folded into one.
// If any Matcher succeeds the rest of the matchers will **not** be called.
// E.g. if `m1` succeeds and replaces `Abs2` with a new constant, nor `m2` or `m3` will be called
// However, sometimes, you will need more than one fusion occur on the same node.
// In this case, you should be able to request another pass of GraphRewrite.
// To request another pass, you will need to register fusions in a callback:
// i.e. you will need to pass `this` into a callback and then call `this->construct_X`
// This will schedule another pass of GraphRewrite with the following fusion.
// This approach should only be used if you are either:
// a) need more than one fusion occur on the same node
// b) you are modifying nodes after the current node in the topological order
// c) there's no linear order of fusions which will give
//    the correct final fusion. i.e. the same fusion needs to occur before and after some other fusion

bool pass::GraphRewrite::run_on_function(shared_ptr<Function> f)
{
    bool rewritten = false;
    const size_t NUM_TRIES = 10;
    size_t tries = NUM_TRIES;
    vector<MatchClosure> original_matchers{m_matchers};
    // This check is very expensive and is only needed for experimental features, so we will hide
    // it behind an environment variable for now. TODO: Find a less expensive way to handle this.
    static bool s_rerun_dynamic_check =
        (std::getenv("NGRAPH_GRAPH_REWRITE_RERUN_DYNAMIC_CHECK") != nullptr);
    bool is_dyn_func = s_rerun_dynamic_check && f->is_dynamic();
    do
    {
        rewritten = false;
        // m_matchers may contain newly constructed matchers for matchers
        // that need multiple passes. See comments above.
        vector<MatchClosure> matchers_to_run{m_matchers};
        m_matchers.clear();
        for (auto node : f->get_ordered_ops())
        {
            for (auto& closure : matchers_to_run)
            {
                if (is_dyn_func && closure.property[PassProperty::REQUIRE_STATIC_SHAPE])
                {
                    NGRAPH_DEBUG << "matcher callback requires static shape but the "
                                    "function is dynamic, skipping this "
                                    "optimization till the shapes are fully "
                                    "materialized";
                    continue;
                }
                NGRAPH_DEBUG << "Running matcher " << closure.matcher->get_name() << "("
                             << closure.matcher->get_pattern()->get_name() << ") on "
                             << node->get_name();
                if (closure.matcher->match(node))
                {
                    NGRAPH_DEBUG << "Matcher " << closure.matcher << closure.matcher->get_name()
                                 << " matched " << node->get_name();
                    if (closure.callback(*closure.matcher.get()))
                    {
                        rewritten = true;
                        // If call back may change function's is_dynamic state, we need to
                        // update the cached value.
                        if (closure.property.is_set(PassProperty::CHANGE_DYNAMIC_STATE))
                        {
                            is_dyn_func = s_rerun_dynamic_check && f->is_dynamic();
                        }
                        break;
                    }
                }
            }
        }

    } while (rewritten && m_matchers.size() > 0 && tries--);

    m_matchers.assign(original_matchers.begin(), original_matchers.end());
    return (NUM_TRIES - tries) > 1; //this means a graph was transformed
}

static vector<regex> initialize_fusion_regexes()
{
    const char* cnsf = getenv("NGRAPH_DISABLED_FUSIONS");
    vector<regex> regexes;
    if (cnsf)
    {
        const string nsf = cnsf;
        const auto sregexes = split(nsf, ';');

        transform(sregexes.begin(),
                  sregexes.end(),
                  back_inserter(regexes),
                  [](const string& c) -> regex { return regex(c); });
    }
    return regexes;
}

bool pass::GraphRewrite::is_enabled(const shared_ptr<pattern::Matcher>& m) const
{
    //note, regexes are static to avoid re-initialization
    static const auto regexes = initialize_fusion_regexes();

    for (const auto& regex : regexes)
    {
        if (regex_match(m->get_name(), regex))
        {
            NGRAPH_DEBUG << "Disabling matcher " << m->get_name();
            return false;
        }
    }

    return true;
}

void pass::GraphRewrite::add_matcher(const shared_ptr<pattern::Matcher>& m,
                                     const graph_rewrite_callback& callback,
                                     const PassPropertyMask& property)
{
    if (is_enabled(m))
    {
        m_matchers.push_back({m, callback, property});
        // If any matcher call back may change dynamic state, we need to
        // update the pass property.
        if (property.is_set(PassProperty::CHANGE_DYNAMIC_STATE))
        {
            set_property(PassProperty::CHANGE_DYNAMIC_STATE, true);
        }
    }
}

void pass::GraphRewrite::add_matcher(const shared_ptr<pattern::Matcher>& m,
                                     const graph_rewrite_callback& callback)
{
    // TODO: before deprecate this function, by default expect the
    // callback require static shape.
    add_matcher(m, callback, {PassProperty::REQUIRE_STATIC_SHAPE});
}

void pass::RecurrentGraphRewrite::add_matcher(
    const std::shared_ptr<pattern::RecurrentMatcher>& m,
    const ngraph::recurrent_graph_rewrite_callback& callback,
    const PassPropertyMask& property)
{
    m_matchers.push_back({m, callback, property});
    // If any matcher call back may change dynamic state, we need to
    // update the pass property.
    if (property.is_set(PassProperty::CHANGE_DYNAMIC_STATE))
    {
        set_property(PassProperty::CHANGE_DYNAMIC_STATE, true);
    }
}

void pass::RecurrentGraphRewrite::add_matcher(
    const std::shared_ptr<pattern::RecurrentMatcher>& m,
    const ngraph::recurrent_graph_rewrite_callback& callback)
{
    // TODO: before deprecate this function, by default expect the
    // callback require static shape.
    add_matcher(m, callback, {PassProperty::REQUIRE_STATIC_SHAPE});
}

bool pass::RecurrentGraphRewrite::run_on_function(shared_ptr<Function> f)
{
    bool changed = false;
    size_t i = 0;

    // This check is very expensive and is only needed for experimental features, so we will hide
    // it behind an environment variable for now. TODO: Find a less expensive way to handle this.
    static bool s_rerun_dynamic_check =
        (std::getenv("NGRAPH_GRAPH_REWRITE_RERUN_DYNAMIC_CHECK") != nullptr);

    auto run_matchers = [&]() -> bool {
        bool is_dyn_func = s_rerun_dynamic_check && f->is_dynamic();
        for (auto node : f->get_ops())
        {
            for (auto& closure : m_matchers)
            {
                if (is_dyn_func && closure.property[PassProperty::REQUIRE_STATIC_SHAPE])
                {
                    NGRAPH_DEBUG << "matcher callback requires static shape but the "
                                    "function is dynamic, skipping this "
                                    "optimization till the shapes are fully "
                                    "materialized";
                    continue;
                }
                NGRAPH_DEBUG << "Running matcher " << closure.matcher << " on " << node->get_name();
                if (closure.matcher->match(node))
                {
                    NGRAPH_DEBUG << "Matcher " << closure.matcher << " matched "
                                 << node->get_name();
                    if (closure.callback(*closure.matcher.get()))
                    {
                        // If call back may change function's is_dynamic state, we need to
                        // update the cached value.
                        if (closure.property.is_set(PassProperty::CHANGE_DYNAMIC_STATE))
                        {
                            is_dyn_func = s_rerun_dynamic_check && f->is_dynamic();
                        }
                        return true;
                    }
                }
            }
        }
        return false;
    };

    do
    {
        changed = run_matchers();
        i++;
    } while (changed && i < m_num_iters);
    return changed;
}
<|endoftext|>


<commit_before>extern "C" {
	#include <ngx_config.h>
	#include <ngx_core.h>
	#include <ngx_http.h>

	/* Directive handlers */
	static char *ngx_http_lmdb_queue(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); // Declare lmdb_queue
	static char *ngx_http_lmdb_queue_topic(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); // Declare lmdb_queue topic
	static char *ngx_http_lmdb_queue_push(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); // Declare lmdb_queue topic

	/* Directives */
	static ngx_command_t ngx_http_lmdb_queue_commands[] = {
		{ ngx_string("lmdb_queue"),
		  NGX_HTTP_MAIN_CONF | NGX_CONF_TAKE2,
		  ngx_http_lmdb_queue,
		  NGX_HTTP_MAIN_CONF_OFFSET,
		  0,
		  NULL },
		{ ngx_string("lmdb_queue_topic"),
		  NGX_HTTP_MAIN_CONF | NGX_CONF_TAKE3,
		  ngx_http_lmdb_queue_topic,
		  NGX_HTTP_MAIN_CONF_OFFSET,
		  0,
		  NULL },
		{ ngx_string("lmdb_queue_push"),
		  NGX_HTTP_MAIN_CONF | NGX_CONF_TAKE2,
		  ngx_http_lmdb_queue_push,
		  NGX_HTTP_LOC_CONF_OFFSET,
		  0,
		  NULL },
		ngx_null_command
	};

	static ngx_http_module_t ngx_http_lmdb_queue_module_ctx = {
		NULL, /* preconfiguration */
		NULL, /* postconfiguration */

		NULL, /* create main configuration */
		NULL, /* init main configuration */

		NULL, /* create server configuration */
		NULL, /* merge server configuration */

		NULL, /* create location configuration */
		NULL  /* merge location configuration */
	};

	ngx_module_t  ngx_http_lmdb_queue_module = {
	    NGX_MODULE_V1,
	    &ngx_http_lmdb_queue_module_ctx,       /* module context */
	    ngx_http_lmdb_queue_commands,          /* module directives */
	    NGX_HTTP_MODULE,                       /* module type */
	    NULL,                                  /* init master */
	    NULL,                                  /* init module */
	    NULL,                                  /* init process */
	    NULL,                                  /* init thread */
	    NULL,                                  /* exit thread */
	    NULL,                                  /* exit process */
	    NULL,                                  /* exit master */
	    NGX_MODULE_V1_PADDING
	};

	static char *ngx_http_lmdb_queue(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {
		return NGX_CONF_OK;
	}

	static char *ngx_http_lmdb_queue_topic(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {
		return NGX_CONF_OK;
	}

	static char *ngx_http_lmdb_queue_push(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {
		return NGX_CONF_OK;
	}
}<commit_msg>fix config pos<commit_after>extern "C" {
	#include <ngx_config.h>
	#include <ngx_core.h>
	#include <ngx_http.h>

	/* Directive handlers */
	static char *ngx_http_lmdb_queue(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); // Declare lmdb_queue
	static char *ngx_http_lmdb_queue_topic(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); // Declare lmdb_queue topic
	static char *ngx_http_lmdb_queue_push(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); // Declare lmdb_queue topic

	/* Directives */
	static ngx_command_t ngx_http_lmdb_queue_commands[] = {
		{ ngx_string("lmdb_queue"),
		  NGX_HTTP_MAIN_CONF | NGX_CONF_TAKE2,
		  ngx_http_lmdb_queue,
		  NGX_HTTP_MAIN_CONF_OFFSET,
		  0,
		  NULL },
		{ ngx_string("lmdb_queue_topic"),
		  NGX_HTTP_MAIN_CONF | NGX_CONF_TAKE3,
		  ngx_http_lmdb_queue_topic,
		  NGX_HTTP_MAIN_CONF_OFFSET,
		  0,
		  NULL },
		{ ngx_string("lmdb_queue_push"),
		  NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_TAKE2,
		  ngx_http_lmdb_queue_push,
		  NGX_HTTP_LOC_CONF_OFFSET,
		  0,
		  NULL },
		ngx_null_command
	};

	static ngx_http_module_t ngx_http_lmdb_queue_module_ctx = {
		NULL, /* preconfiguration */
		NULL, /* postconfiguration */

		NULL, /* create main configuration */
		NULL, /* init main configuration */

		NULL, /* create server configuration */
		NULL, /* merge server configuration */

		NULL, /* create location configuration */
		NULL  /* merge location configuration */
	};

	ngx_module_t  ngx_http_lmdb_queue_module = {
	    NGX_MODULE_V1,
	    &ngx_http_lmdb_queue_module_ctx,       /* module context */
	    ngx_http_lmdb_queue_commands,          /* module directives */
	    NGX_HTTP_MODULE,                       /* module type */
	    NULL,                                  /* init master */
	    NULL,                                  /* init module */
	    NULL,                                  /* init process */
	    NULL,                                  /* init thread */
	    NULL,                                  /* exit thread */
	    NULL,                                  /* exit process */
	    NULL,                                  /* exit master */
	    NGX_MODULE_V1_PADDING
	};

	static char *ngx_http_lmdb_queue(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {
		return NGX_CONF_OK;
	}

	static char *ngx_http_lmdb_queue_topic(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {
		return NGX_CONF_OK;
	}

	static char *ngx_http_lmdb_queue_push(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {
		return NGX_CONF_OK;
	}
}<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ImpressModule.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2007-04-03 15:52:53 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include "precompiled_sd.hxx"

#include "framework/ImpressModule.hxx"

#include "framework/FrameworkHelper.hxx"
#include "ViewTabBarModule.hxx"
#include "CenterViewFocusModule.hxx"
#include "SlideSorterModule.hxx"
#include "TaskPaneModule.hxx"

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;

namespace sd { namespace framework {

void ImpressModule::Initialize (Reference<frame::XController>& rxController)
{
    new CenterViewFocusModule(rxController);
    new ViewTabBarModule(
        rxController,
        FrameworkHelper::CreateResourceId(
            FrameworkHelper::msViewTabBarURL,
            FrameworkHelper::msCenterPaneURL));
    new SlideSorterModule(
        rxController,
        FrameworkHelper::msLeftImpressPaneURL);
    TaskPaneModule::Initialize(rxController);
}

} } // end of namespace sd::framework
<commit_msg>INTEGRATION: CWS impress124 (1.2.84); FILE MERGED 2007/07/19 15:41:32 af 1.2.84.1: #i77179# Added ShellStackGuard.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ImpressModule.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: vg $ $Date: 2008-01-29 08:19:48 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include "precompiled_sd.hxx"

#include "framework/ImpressModule.hxx"

#include "framework/FrameworkHelper.hxx"
#include "ViewTabBarModule.hxx"
#include "CenterViewFocusModule.hxx"
#include "SlideSorterModule.hxx"
#include "TaskPaneModule.hxx"
#include "ShellStackGuard.hxx"

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;

namespace sd { namespace framework {

void ImpressModule::Initialize (Reference<frame::XController>& rxController)
{
    new CenterViewFocusModule(rxController);
    new ViewTabBarModule(
        rxController,
        FrameworkHelper::CreateResourceId(
            FrameworkHelper::msViewTabBarURL,
            FrameworkHelper::msCenterPaneURL));
    new SlideSorterModule(
        rxController,
        FrameworkHelper::msLeftImpressPaneURL);
    TaskPaneModule::Initialize(rxController);
    new ShellStackGuard(rxController);
}

} } // end of namespace sd::framework
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "propertyeditorvalue.h"
#include <abstractview.h>
#include <nodeabstractproperty.h>
#include <nodeproperty.h>
#include <model.h>
#include <nodemetainfo.h>
#include <metainfo.h>
#include <propertymetainfo.h>
#include <nodeproperty.h>
#include <qmlobjectnode.h>

//using namespace QmlDesigner;

PropertyEditorValue::PropertyEditorValue(QObject *parent)
   : QObject(parent),
   m_isInSubState(false),
   m_isInModel(false),
   m_isBound(false),
   m_isValid(false),
   m_complexNode(new PropertyEditorNodeWrapper(this))
{
}

QVariant PropertyEditorValue::value() const
{
    QVariant returnValue = m_value;
    if (modelNode().isValid() && modelNode().metaInfo().isValid() && modelNode().metaInfo().property(name()).isValid())
        if (modelNode().metaInfo().property(name()).type() == QLatin1String("QUrl")) {
        returnValue = returnValue.toUrl().toString();
    }
    return returnValue;
}

static bool cleverDoubleCompare(QVariant value1, QVariant value2)
{ //we ignore slight changes on doubles
    if ((value1.type() == QVariant::Double) && (value2.type() == QVariant::Double)) {
        int a = value1.toDouble() * 100;
        int b = value2.toDouble() * 100;

        if (qFuzzyCompare((qreal(a) / 100), (qreal(b) / 100))) {
            return true;
        }
    }
    return false;
}

void PropertyEditorValue::setValueWithEmit(const QVariant &value)
{
    if ( m_value != value) {
        QVariant newValue = value;
        if (modelNode().isValid() && modelNode().metaInfo().isValid() && modelNode().metaInfo().property(name()).isValid())
            if (modelNode().metaInfo().property(name()).type() == QLatin1String("QUrl")) {
            newValue = QUrl(newValue.toString());
        }

        if (cleverDoubleCompare(newValue, m_value))
            return;
        setValue(newValue);
        m_isBound = false;
        emit valueChanged(name(), value);
        emit isBoundChanged();
    }
}

void PropertyEditorValue::setValue(const QVariant &value)
{
    if ( m_value != value) {
        m_value = value;
        emit valueChanged(QString(), value);
    }
    emit isBoundChanged();
}

QString PropertyEditorValue::expression() const
{

    return m_expression;
}

void PropertyEditorValue::setExpressionWithEmit(const QString &expression)
{
    if ( m_expression != expression) {
        setExpression(expression);
        emit expressionChanged(name());
    }
}

void PropertyEditorValue::setExpression(const QString &expression)
{
    if ( m_expression != expression) {
        m_expression = expression;
        emit expressionChanged(QString());
    }
}

bool PropertyEditorValue::isInSubState() const
{
    const QmlDesigner::QmlObjectNode objectNode(modelNode());
    return objectNode.isValid() && objectNode.propertyAffectedByCurrentState(name());
}

bool PropertyEditorValue::isBound() const
{
    return modelNode().isValid() && modelNode().property(name()).isValid() && modelNode().property(name()).isBindingProperty();
}

bool PropertyEditorValue::isInModel() const
{
    return modelNode().isValid() && modelNode().hasProperty(name());
}

QString PropertyEditorValue::name() const
{
    return m_name;
}

void PropertyEditorValue::setName(const QString &name)
{
    m_name = name;
}

bool PropertyEditorValue::isValid() const
{
    return m_isValid;
}

void PropertyEditorValue::setIsValid(bool valid)
{
    m_isValid = valid;
}

ModelNode PropertyEditorValue::modelNode() const
{
    return m_modelNode;
}

void PropertyEditorValue::setModelNode(const ModelNode &modelNode)
{
    if (modelNode != m_modelNode) {
        m_modelNode = modelNode;
        m_complexNode->update();
        emit modelNodeChanged();
    }
}

PropertyEditorNodeWrapper* PropertyEditorValue::complexNode()
{
    return m_complexNode;
}

void PropertyEditorValue::resetValue()
{
    if (m_value.isValid()) {
        setValue(QVariant());
        m_isBound = false;
        emit valueChanged(name(), QVariant());
    }
}

void PropertyEditorValue::registerDeclarativeTypes()
{
    qmlRegisterType<PropertyEditorValue>("Bauhaus",1,0,"PropertyEditorValue");
    qmlRegisterType<PropertyEditorNodeWrapper>("Bauhaus",1,0,"PropertyEditorNodeWrapper");
    qmlRegisterType<QDeclarativePropertyMap>("Bauhaus",1,0,"QDeclarativePropertyMap");
}

PropertyEditorNodeWrapper::PropertyEditorNodeWrapper(PropertyEditorValue* parent) : m_valuesPropertyMap(this)
{
    m_editorValue = parent;
    connect(m_editorValue, SIGNAL(modelNodeChanged()), this, SLOT(update()));
}

PropertyEditorNodeWrapper::PropertyEditorNodeWrapper(QObject *parent) : QObject(parent)
{
}

bool PropertyEditorNodeWrapper::exists()
{
    if (!(m_editorValue && m_editorValue->modelNode().isValid()))
        return false;

    return m_modelNode.isValid();
}

QString PropertyEditorNodeWrapper::type()
{
    if (!(m_modelNode.isValid()))
        return QString("");

    return m_modelNode.simplifiedTypeName();

}

ModelNode PropertyEditorNodeWrapper::parentModelNode() const
{
    return  m_editorValue->modelNode();
}

QString PropertyEditorNodeWrapper::propertyName() const
{
    return m_editorValue->name();
}

QDeclarativePropertyMap* PropertyEditorNodeWrapper::properties()
{
    return &m_valuesPropertyMap;
}

void PropertyEditorNodeWrapper::add(const QString &type)
{

    QString propertyType = type;

    if ((m_editorValue && m_editorValue->modelNode().isValid())) {
        if (propertyType.isEmpty())
            propertyType = m_editorValue->modelNode().metaInfo().property(m_editorValue->name()).type();
        while (propertyType.contains('*')) //strip star
            propertyType.chop(1);
        m_modelNode = m_editorValue->modelNode().view()->createModelNode(propertyType, 4, 6);
        m_editorValue->modelNode().nodeAbstractProperty(m_editorValue->name()).reparentHere(m_modelNode);
        if (!m_modelNode.isValid()) {
            qWarning("PropertyEditorNodeWrapper::add failed");
        }
    } else {
        qWarning("PropertyEditorNodeWrapper::add failed - node invalid");
    }
    setup();
}

void PropertyEditorNodeWrapper::remove()
{
    if ((m_editorValue && m_editorValue->modelNode().isValid())) {
        if (QmlDesigner::QmlObjectNode(m_modelNode).isValid())
            QmlDesigner::QmlObjectNode(m_modelNode).destroy();
        m_editorValue->modelNode().removeProperty(m_editorValue->name());
    } else {
        qWarning("PropertyEditorNodeWrapper::remove failed - node invalid");
    }
    m_modelNode = QmlDesigner::ModelNode();

    foreach (const QString &propertyName, m_valuesPropertyMap.keys())
        m_valuesPropertyMap.clear(propertyName);
    foreach (QObject *object, m_valuesPropertyMap.children())
        delete object;
    emit propertiesChanged();
    emit existsChanged();
}

void PropertyEditorNodeWrapper::changeValue(const QString &name)
{
    if (name.isNull())
        return;
    if (m_modelNode.isValid()) {
        QmlDesigner::QmlObjectNode fxObjectNode(m_modelNode);

        PropertyEditorValue *valueObject = qvariant_cast<PropertyEditorValue *>(m_valuesPropertyMap.value(name));

        if (valueObject->value().isValid())
            fxObjectNode.setVariantProperty(name, valueObject->value());
        else
            fxObjectNode.removeVariantProperty(name);
    }
}

void PropertyEditorNodeWrapper::setup()
{
    Q_ASSERT(m_editorValue);
    Q_ASSERT(m_editorValue->modelNode().isValid());
    if ((m_editorValue->modelNode().isValid() && m_modelNode.isValid())) {
        QmlDesigner::QmlObjectNode fxObjectNode(m_modelNode);
        foreach ( const QString &propertyName, m_valuesPropertyMap.keys())
            m_valuesPropertyMap.clear(propertyName);
        foreach (QObject *object, m_valuesPropertyMap.children())
            delete object;

        foreach (const QString &propertyName, m_modelNode.metaInfo().properties().keys()) {
            PropertyEditorValue *valueObject = new PropertyEditorValue(&m_valuesPropertyMap);
            valueObject->setName(propertyName);
            valueObject->setValue(fxObjectNode.instanceValue(propertyName));

            connect(valueObject, SIGNAL(valueChanged(QString, const QVariant&)), &m_valuesPropertyMap, SIGNAL(valueChanged(QString, const QVariant&)));
            m_valuesPropertyMap.insert(propertyName, QVariant::fromValue(valueObject));
        }
    }
    connect(&m_valuesPropertyMap, SIGNAL(valueChanged(const QString &, const QVariant&)), this, SLOT(changeValue(const QString&)));

    emit propertiesChanged();
    emit existsChanged();
}

void PropertyEditorNodeWrapper::update()
{
    if (m_editorValue && m_editorValue->modelNode().isValid()) {
        if (m_editorValue->modelNode().hasProperty(m_editorValue->name()) && m_editorValue->modelNode().property(m_editorValue->name()).isNodeProperty()) {
            m_modelNode = m_editorValue->modelNode().nodeProperty(m_editorValue->name()).modelNode();
        }
        setup();
        emit existsChanged();
        emit typeChanged();
    }
}

<commit_msg>QmlDesigner.propertyEditor emit in all cases to fix color coding<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "propertyeditorvalue.h"
#include <abstractview.h>
#include <nodeabstractproperty.h>
#include <nodeproperty.h>
#include <model.h>
#include <nodemetainfo.h>
#include <metainfo.h>
#include <propertymetainfo.h>
#include <nodeproperty.h>
#include <qmlobjectnode.h>

//using namespace QmlDesigner;

PropertyEditorValue::PropertyEditorValue(QObject *parent)
   : QObject(parent),
   m_isInSubState(false),
   m_isInModel(false),
   m_isBound(false),
   m_isValid(false),
   m_complexNode(new PropertyEditorNodeWrapper(this))
{
}

QVariant PropertyEditorValue::value() const
{
    QVariant returnValue = m_value;
    if (modelNode().isValid() && modelNode().metaInfo().isValid() && modelNode().metaInfo().property(name()).isValid())
        if (modelNode().metaInfo().property(name()).type() == QLatin1String("QUrl")) {
        returnValue = returnValue.toUrl().toString();
    }
    return returnValue;
}

static bool cleverDoubleCompare(QVariant value1, QVariant value2)
{ //we ignore slight changes on doubles
    if ((value1.type() == QVariant::Double) && (value2.type() == QVariant::Double)) {
        int a = value1.toDouble() * 100;
        int b = value2.toDouble() * 100;

        if (qFuzzyCompare((qreal(a) / 100), (qreal(b) / 100))) {
            return true;
        }
    }
    return false;
}

void PropertyEditorValue::setValueWithEmit(const QVariant &value)
{
    if ( m_value != value) {
        QVariant newValue = value;
        if (modelNode().isValid() && modelNode().metaInfo().isValid() && modelNode().metaInfo().property(name()).isValid())
            if (modelNode().metaInfo().property(name()).type() == QLatin1String("QUrl")) {
            newValue = QUrl(newValue.toString());
        }

        if (cleverDoubleCompare(newValue, m_value))
            return;
        setValue(newValue);
        m_isBound = false;
        emit valueChanged(name(), value);
        emit isBoundChanged();
    }
}

void PropertyEditorValue::setValue(const QVariant &value)
{
    if ( m_value != value) {
        m_value = value;
    }
    emit valueChanged(QString(), value);
    emit isBoundChanged();
}

QString PropertyEditorValue::expression() const
{

    return m_expression;
}

void PropertyEditorValue::setExpressionWithEmit(const QString &expression)
{
    if ( m_expression != expression) {
        setExpression(expression);
        emit expressionChanged(name());
    }
}

void PropertyEditorValue::setExpression(const QString &expression)
{
    if ( m_expression != expression) {
        m_expression = expression;
        emit expressionChanged(QString());
    }
}

bool PropertyEditorValue::isInSubState() const
{
    const QmlDesigner::QmlObjectNode objectNode(modelNode());
    return objectNode.isValid() && objectNode.propertyAffectedByCurrentState(name());
}

bool PropertyEditorValue::isBound() const
{
    return modelNode().isValid() && modelNode().property(name()).isValid() && modelNode().property(name()).isBindingProperty();
}

bool PropertyEditorValue::isInModel() const
{
    qDebug() << name();
    qDebug() << (modelNode().isValid() && modelNode().hasProperty(name()));
    return modelNode().isValid() && modelNode().hasProperty(name());
}

QString PropertyEditorValue::name() const
{
    return m_name;
}

void PropertyEditorValue::setName(const QString &name)
{
    m_name = name;
}

bool PropertyEditorValue::isValid() const
{
    return m_isValid;
}

void PropertyEditorValue::setIsValid(bool valid)
{
    m_isValid = valid;
}

ModelNode PropertyEditorValue::modelNode() const
{
    return m_modelNode;
}

void PropertyEditorValue::setModelNode(const ModelNode &modelNode)
{
    if (modelNode != m_modelNode) {
        m_modelNode = modelNode;
        m_complexNode->update();
        emit modelNodeChanged();
    }
}

PropertyEditorNodeWrapper* PropertyEditorValue::complexNode()
{
    return m_complexNode;
}

void PropertyEditorValue::resetValue()
{
    if (m_value.isValid()) {
        setValue(QVariant());
        m_isBound = false;
        emit valueChanged(name(), QVariant());
    }
}

void PropertyEditorValue::registerDeclarativeTypes()
{
    qmlRegisterType<PropertyEditorValue>("Bauhaus",1,0,"PropertyEditorValue");
    qmlRegisterType<PropertyEditorNodeWrapper>("Bauhaus",1,0,"PropertyEditorNodeWrapper");
    qmlRegisterType<QDeclarativePropertyMap>("Bauhaus",1,0,"QDeclarativePropertyMap");
}

PropertyEditorNodeWrapper::PropertyEditorNodeWrapper(PropertyEditorValue* parent) : m_valuesPropertyMap(this)
{
    m_editorValue = parent;
    connect(m_editorValue, SIGNAL(modelNodeChanged()), this, SLOT(update()));
}

PropertyEditorNodeWrapper::PropertyEditorNodeWrapper(QObject *parent) : QObject(parent)
{
}

bool PropertyEditorNodeWrapper::exists()
{
    if (!(m_editorValue && m_editorValue->modelNode().isValid()))
        return false;

    return m_modelNode.isValid();
}

QString PropertyEditorNodeWrapper::type()
{
    if (!(m_modelNode.isValid()))
        return QString("");

    return m_modelNode.simplifiedTypeName();

}

ModelNode PropertyEditorNodeWrapper::parentModelNode() const
{
    return  m_editorValue->modelNode();
}

QString PropertyEditorNodeWrapper::propertyName() const
{
    return m_editorValue->name();
}

QDeclarativePropertyMap* PropertyEditorNodeWrapper::properties()
{
    return &m_valuesPropertyMap;
}

void PropertyEditorNodeWrapper::add(const QString &type)
{

    QString propertyType = type;

    if ((m_editorValue && m_editorValue->modelNode().isValid())) {
        if (propertyType.isEmpty())
            propertyType = m_editorValue->modelNode().metaInfo().property(m_editorValue->name()).type();
        while (propertyType.contains('*')) //strip star
            propertyType.chop(1);
        m_modelNode = m_editorValue->modelNode().view()->createModelNode(propertyType, 4, 6);
        m_editorValue->modelNode().nodeAbstractProperty(m_editorValue->name()).reparentHere(m_modelNode);
        if (!m_modelNode.isValid()) {
            qWarning("PropertyEditorNodeWrapper::add failed");
        }
    } else {
        qWarning("PropertyEditorNodeWrapper::add failed - node invalid");
    }
    setup();
}

void PropertyEditorNodeWrapper::remove()
{
    if ((m_editorValue && m_editorValue->modelNode().isValid())) {
        if (QmlDesigner::QmlObjectNode(m_modelNode).isValid())
            QmlDesigner::QmlObjectNode(m_modelNode).destroy();
        m_editorValue->modelNode().removeProperty(m_editorValue->name());
    } else {
        qWarning("PropertyEditorNodeWrapper::remove failed - node invalid");
    }
    m_modelNode = QmlDesigner::ModelNode();

    foreach (const QString &propertyName, m_valuesPropertyMap.keys())
        m_valuesPropertyMap.clear(propertyName);
    foreach (QObject *object, m_valuesPropertyMap.children())
        delete object;
    emit propertiesChanged();
    emit existsChanged();
}

void PropertyEditorNodeWrapper::changeValue(const QString &name)
{
    if (name.isNull())
        return;
    if (m_modelNode.isValid()) {
        QmlDesigner::QmlObjectNode fxObjectNode(m_modelNode);

        PropertyEditorValue *valueObject = qvariant_cast<PropertyEditorValue *>(m_valuesPropertyMap.value(name));

        if (valueObject->value().isValid())
            fxObjectNode.setVariantProperty(name, valueObject->value());
        else
            fxObjectNode.removeVariantProperty(name);
    }
}

void PropertyEditorNodeWrapper::setup()
{
    Q_ASSERT(m_editorValue);
    Q_ASSERT(m_editorValue->modelNode().isValid());
    if ((m_editorValue->modelNode().isValid() && m_modelNode.isValid())) {
        QmlDesigner::QmlObjectNode fxObjectNode(m_modelNode);
        foreach ( const QString &propertyName, m_valuesPropertyMap.keys())
            m_valuesPropertyMap.clear(propertyName);
        foreach (QObject *object, m_valuesPropertyMap.children())
            delete object;

        foreach (const QString &propertyName, m_modelNode.metaInfo().properties().keys()) {
            PropertyEditorValue *valueObject = new PropertyEditorValue(&m_valuesPropertyMap);
            valueObject->setName(propertyName);
            valueObject->setValue(fxObjectNode.instanceValue(propertyName));

            connect(valueObject, SIGNAL(valueChanged(QString, const QVariant&)), &m_valuesPropertyMap, SIGNAL(valueChanged(QString, const QVariant&)));
            m_valuesPropertyMap.insert(propertyName, QVariant::fromValue(valueObject));
        }
    }
    connect(&m_valuesPropertyMap, SIGNAL(valueChanged(const QString &, const QVariant&)), this, SLOT(changeValue(const QString&)));

    emit propertiesChanged();
    emit existsChanged();
}

void PropertyEditorNodeWrapper::update()
{
    if (m_editorValue && m_editorValue->modelNode().isValid()) {
        if (m_editorValue->modelNode().hasProperty(m_editorValue->name()) && m_editorValue->modelNode().property(m_editorValue->name()).isNodeProperty()) {
            m_modelNode = m_editorValue->modelNode().nodeProperty(m_editorValue->name()).modelNode();
        }
        setup();
        emit existsChanged();
        emit typeChanged();
    }
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: sprite.hxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: kz $ $Date: 2005-11-02 13:03:59 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef INCLUDED_VCLCANVAS_SPRITE_HXX
#define INCLUDED_VCLCANVAS_SPRITE_HXX

#include <canvas/base/sprite.hxx>

class OutputDevice;

namespace vclcanvas
{
    /** Specialization of ::canvas::Sprite interface, to also provide
        redraw methods.
     */
    class Sprite : public ::canvas::Sprite
    {
    public:

        /** Redraw sprite at the stored position.

            @param bBufferedUpdate
            When true, the redraw does not happen directly on
            the front buffer, but within a VDev. Used to speed up
            drawing.
         */
        virtual void redraw( OutputDevice& rOutDev,
                             bool          bBufferedUpdate ) const = 0;

        /** Redraw sprite at the given position.

            @param rPos
            Output position of the sprite. Overrides the sprite's own
            output position.

            @param bBufferedUpdate
            When true, the redraw does not happen directly on
            the front buffer, but within a VDev. Used to speed up
            drawing.
         */
        virtual void redraw( OutputDevice&              rOutDev,
                             const ::basegfx::B2DPoint& rPos,
                             bool                       bBufferedUpdate ) const = 0;
    };
}

#endif /* INCLUDED_VCLCANVAS_SPRITE_HXX */
<commit_msg>INTEGRATION: CWS changefileheader (1.7.136); FILE MERGED 2008/03/28 16:35:17 rt 1.7.136.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: sprite.hxx,v $
 * $Revision: 1.8 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef INCLUDED_VCLCANVAS_SPRITE_HXX
#define INCLUDED_VCLCANVAS_SPRITE_HXX

#include <canvas/base/sprite.hxx>

class OutputDevice;

namespace vclcanvas
{
    /** Specialization of ::canvas::Sprite interface, to also provide
        redraw methods.
     */
    class Sprite : public ::canvas::Sprite
    {
    public:

        /** Redraw sprite at the stored position.

            @param bBufferedUpdate
            When true, the redraw does not happen directly on
            the front buffer, but within a VDev. Used to speed up
            drawing.
         */
        virtual void redraw( OutputDevice& rOutDev,
                             bool          bBufferedUpdate ) const = 0;

        /** Redraw sprite at the given position.

            @param rPos
            Output position of the sprite. Overrides the sprite's own
            output position.

            @param bBufferedUpdate
            When true, the redraw does not happen directly on
            the front buffer, but within a VDev. Used to speed up
            drawing.
         */
        virtual void redraw( OutputDevice&              rOutDev,
                             const ::basegfx::B2DPoint& rPos,
                             bool                       bBufferedUpdate ) const = 0;
    };
}

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


<commit_before>/* Numenta Platform for Intelligent Computing (NuPIC)
 * Copyright (C) 2017, Numenta, Inc.  Unless you have an agreement
 * with Numenta, Inc., for a separate license for this software code, the
 * following terms and conditions apply:
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero Public License version 3 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero Public License for more details.
 *
 * You should have received a copy of the GNU Affero Public License
 * along with this program.  If not, see http://www.gnu.org/licenses.
 *
 * http://numenta.org/licenses/
 * ---------------------------------------------------------------------
 */

#ifndef NUPIC_UTIL_SLIDING_WINDOW_HPP
#define NUPIC_UTIL_SLIDING_WINDOW_HPP

#include <vector>
#include <algorithm>

#include <nupic/types/Types.hpp>
#include <nupic/utils/Log.hpp>

namespace nupic {
  namespace util {

    template<class T>
    class SlidingWindow {
      public:
        SlidingWindow(UInt maxCapacity);
        SlidingWindow(UInt maxCapacity, std::vector<T> initialData);
        const UInt maxCapacity;
        size_t size() const;
        /** append new value to the end of the buffer and handle the
           "overflows"-may pop the first element if full.
        */
        void append(T newValue);

        /** like append, but return the dropped value. isValid indicates
            if the return value is valid (not while size()< maxCapacity)
          :param T newValue - new value to append to the sliding window
          :param bool isValid - a return pass-by-value that indicates validity
             of the return T value. for first maxCapacity items it is false,
             later always true.
          :return T dropped value (past oldest element) if isValid;
             if not valid, this field holds the oldest value
             (but still contained in the window!)
        */
        T append(T newValue, bool& isValid);

        /**
        * :return unordered content (data ) of this sl. window;
             call getLinearizedData() if you need them oredered from
             oldest->newest
        * This direct access method is fast.
        */
        const std::vector<T>& getData() const;

        /** linearize method for the internal buffer; this is slower than
            the pure getData() but ensures that the data are ordered (oldest at
             the beginning, newest at the end of the vector
         * This handles case of |5,6;1,2,3,4| => |1,2,3,4,5,6|
         * :return new linearized vector
        */
        std::vector<T> getLinearizedData() const;

        bool operator==(const SlidingWindow& r2) const;
        bool operator!=(const SlidingWindow& r2) const;
        T& operator[](UInt index);
        const T& operator[](UInt index) const;

      private:
        std::vector<T> buffer_;
        UInt idxNext_;
};
}} //end ns

/// IMPLEMENTATION
#include <cmath>

using nupic::util::SlidingWindow;

template<class T>
SlidingWindow<T>::SlidingWindow(nupic::UInt maxCapacity) :
  maxCapacity(maxCapacity) {
  NTA_CHECK(maxCapacity > 0);
  buffer_.reserve(maxCapacity);
  idxNext_ = 0;
}

template<class T>
SlidingWindow<T>::SlidingWindow(nupic::UInt maxCapacity, std::vector<T> initialData)  :
  SlidingWindow(maxCapacity) {
  auto sz = std::min(initialData.size(), (size_t)maxCapacity);
  buffer_.insert(std::begin(buffer_), std::end(initialData) - sz, std::end(initialData));
  idxNext_ = sz % maxCapacity;
}

template<class T>
size_t SlidingWindow<T>::size() const {
  NTA_ASSERT(buffer_.size() <= maxCapacity);
  return buffer_.size();
}

template<class T>
void SlidingWindow<T>::append(T newValue) {
  if(size() < maxCapacity) {
    buffer_.emplace_back(newValue);
  } else {
  buffer_[idxNext_] = newValue;
  }
  //the assignment must be out of the [] above, so not [idxNext_++%maxCap],
  // because we want to store the value %maxCap, not only ++
  idxNext_ = ++idxNext_ %maxCapacity;
}

template<class T>
T SlidingWindow<T>::append(T newValue, bool& isValid) {
  //handle case of empty buffer (access buff[0]), otherwise return oldest elem
  T old = buffer_.empty() ? newValue : buffer_[idxNext_];
  //only in this case we drop oldest; this happens always after
  //first maxCap steps ; must be checked before append()
  isValid = (buffer_.size()==maxCapacity);
  append(newValue);
  return old;
}

template<class T>
const std::vector<T>& SlidingWindow<T>::getData() const {
  return buffer_; //may contain trailing "zeros"
}

template<class T>
std::vector<T> SlidingWindow<T>::getLinearizedData() const {
  std::vector<T> lin;
  lin.reserve(buffer_.size());

  //insert the "older" part at the beginning
  lin.insert(std::begin(lin), std::begin(buffer_) + idxNext_, std::end(buffer_));
  //append the "newer" part to the end of the constructed vect
  lin.insert(std::end(lin), std::begin(buffer_), std::begin(buffer_) + idxNext_);
 return lin;
}

template<class T>
bool SlidingWindow<T>::operator==(const SlidingWindow& r2) const {
  return ((this->size() == r2.size()) && (this->maxCapacity == r2.maxCapacity) &&
    (this->getData()== r2.getData()) );
  //FIXME review the ==, on my machine it randomly passes/fails the test!
}

template<class T>
bool SlidingWindow<T>::operator!=(const SlidingWindow& r2) const {
  return !operator==(r2);
}

template<class T>
T& SlidingWindow<T>::operator[](nupic::UInt index) {
  NTA_ASSERT(index <= size());
  return &buffer_[index];
}

template<class T>
const T& SlidingWindow<T>::operator[](nupic::UInt index) const {
  return this->operator[](index); //call the overloaded operator[] above
}

#endif //header
<commit_msg>SlidingWindow: fix operator[]<commit_after>/* Numenta Platform for Intelligent Computing (NuPIC)
 * Copyright (C) 2017, Numenta, Inc.  Unless you have an agreement
 * with Numenta, Inc., for a separate license for this software code, the
 * following terms and conditions apply:
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero Public License version 3 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero Public License for more details.
 *
 * You should have received a copy of the GNU Affero Public License
 * along with this program.  If not, see http://www.gnu.org/licenses.
 *
 * http://numenta.org/licenses/
 * ---------------------------------------------------------------------
 */

#ifndef NUPIC_UTIL_SLIDING_WINDOW_HPP
#define NUPIC_UTIL_SLIDING_WINDOW_HPP

#include <vector>
#include <algorithm>

#include <nupic/types/Types.hpp>
#include <nupic/utils/Log.hpp>

namespace nupic {
  namespace util {

    template<class T>
    class SlidingWindow {
      public:
        SlidingWindow(UInt maxCapacity);
        SlidingWindow(UInt maxCapacity, std::vector<T> initialData);
        const UInt maxCapacity;
        size_t size() const;
        /** append new value to the end of the buffer and handle the
           "overflows"-may pop the first element if full.
        */
        void append(T newValue);

        /** like append, but return the dropped value. isValid indicates
            if the return value is valid (not while size()< maxCapacity)
          :param T newValue - new value to append to the sliding window
          :param bool isValid - a return pass-by-value that indicates validity
             of the return T value. for first maxCapacity items it is false,
             later always true.
          :return T dropped value (past oldest element) if isValid;
             if not valid, this field holds the oldest value
             (but still contained in the window!)
        */
        T append(T newValue, bool& isValid);

        /**
        * :return unordered content (data ) of this sl. window;
             call getLinearizedData() if you need them oredered from
             oldest->newest
        * This direct access method is fast.
        */
        const std::vector<T>& getData() const;

        /** linearize method for the internal buffer; this is slower than
            the pure getData() but ensures that the data are ordered (oldest at
             the beginning, newest at the end of the vector
         * This handles case of |5,6;1,2,3,4| => |1,2,3,4,5,6|
         * :return new linearized vector
        */
        std::vector<T> getLinearizedData() const;

        bool operator==(const SlidingWindow& r2) const;
        bool operator!=(const SlidingWindow& r2) const;
        T& operator[](UInt index);
        const T& operator[](UInt index) const;

      private:
        std::vector<T> buffer_;
        UInt idxNext_;
};
}} //end ns

/// IMPLEMENTATION
#include <cmath>

using nupic::util::SlidingWindow;

template<class T>
SlidingWindow<T>::SlidingWindow(nupic::UInt maxCapacity) :
  maxCapacity(maxCapacity) {
  NTA_CHECK(maxCapacity > 0);
  buffer_.reserve(maxCapacity);
  idxNext_ = 0;
}

template<class T>
SlidingWindow<T>::SlidingWindow(nupic::UInt maxCapacity, std::vector<T> initialData)  :
  SlidingWindow(maxCapacity) {
  auto sz = std::min(initialData.size(), (size_t)maxCapacity);
  buffer_.insert(std::begin(buffer_), std::end(initialData) - sz, std::end(initialData));
  idxNext_ = sz % maxCapacity;
}

template<class T>
size_t SlidingWindow<T>::size() const {
  NTA_ASSERT(buffer_.size() <= maxCapacity);
  return buffer_.size();
}

template<class T>
void SlidingWindow<T>::append(T newValue) {
  if(size() < maxCapacity) {
    buffer_.emplace_back(newValue);
  } else {
  buffer_[idxNext_] = newValue;
  }
  //the assignment must be out of the [] above, so not [idxNext_++%maxCap],
  // because we want to store the value %maxCap, not only ++
  idxNext_ = ++idxNext_ %maxCapacity;
}

template<class T>
T SlidingWindow<T>::append(T newValue, bool& isValid) {
  //handle case of empty buffer (access buff[0]), otherwise return oldest elem
  T old = buffer_.empty() ? newValue : buffer_[idxNext_];
  //only in this case we drop oldest; this happens always after
  //first maxCap steps ; must be checked before append()
  isValid = (buffer_.size()==maxCapacity);
  append(newValue);
  return old;
}

template<class T>
const std::vector<T>& SlidingWindow<T>::getData() const {
  return buffer_; //may contain trailing "zeros"
}

template<class T>
std::vector<T> SlidingWindow<T>::getLinearizedData() const {
  std::vector<T> lin;
  lin.reserve(buffer_.size());

  //insert the "older" part at the beginning
  lin.insert(std::begin(lin), std::begin(buffer_) + idxNext_, std::end(buffer_));
  //append the "newer" part to the end of the constructed vect
  lin.insert(std::end(lin), std::begin(buffer_), std::begin(buffer_) + idxNext_);
 return lin;
}

template<class T>
bool SlidingWindow<T>::operator==(const SlidingWindow& r2) const {
  return ((this->size() == r2.size()) && (this->maxCapacity == r2.maxCapacity) &&
    (this->getData()== r2.getData()) );
  //FIXME review the ==, on my machine it randomly passes/fails the test!
}

template<class T>
bool SlidingWindow<T>::operator!=(const SlidingWindow& r2) const {
  return !operator==(r2);
}

template<class T>
T& SlidingWindow<T>::operator[](nupic::UInt index) {
  NTA_ASSERT(index <= size());
  //get last updated position, "current"+index(offset)
  //avoid calling getLinearizeData() as it involves copy()
  nupic::UInt currentIdx = (idxNext_ -1 + maxCapacity + index) % maxCapacity;
  return &buffer_[currentIdx];
}

template<class T>
const T& SlidingWindow<T>::operator[](nupic::UInt index) const {
  return this->operator[](index); //call the overloaded operator[] above
}

#endif //header
<|endoftext|>