<commit_before>//  Copyright 2011 Gregory Szorc
//
//  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 <zippylog/zippylog.hpp>
#include <zippylog/testing.hpp>

#include <zippylog/client.hpp>
#include <zippylog/envelope.hpp>
#include <zippylog/lua.hpp>
#include <zippylog/platform.hpp>
#include <zippylog/request_processor.pb.h>
#include <zippylog/device/server.hpp>

extern "C" {
#include <lua.h>
#include <lauxlib.h>
}

#include <iostream>
#include <sstream>
#include <string>
#include <vector>

#include <assert.h>

using ::std::cerr;
using ::std::cout;
using ::std::endl;
using ::std::ostringstream;
using ::std::string;
using ::std::vector;
using ::zippylog::client::Client;
using ::zippylog::Envelope;
using ::zippylog::device::ServerStartParams;
using ::zippylog::lua::LuaState;

#define TIMER_START(iterations) { \
    int TIMER_ITERATIONS = iterations; \
    ::zippylog::platform::Time __tstart; \
    ::zippylog::platform::TimeNow(__tstart); \
    for (int TIMER_LOOP_VALUE = TIMER_ITERATIONS; TIMER_LOOP_VALUE; TIMER_LOOP_VALUE--) { \

#define TIMER_END(description) } \
    ::zippylog::platform::Time __tend; \
    ::zippylog::platform::TimeNow(__tend); \
    uint64 elapsed = __tend.epoch_micro - __tstart.epoch_micro; \
    print_result(description, elapsed, TIMER_ITERATIONS); \
    }

// this is like the one above except we take an int whose value
// we wait to go to the number of iterations
#define TIMER_END_WAIT(description, tracking) } \
    while (tracking != TIMER_ITERATIONS); \
    ::zippylog::platform::Time __tend; \
    ::zippylog::platform::TimeNow(__tend); \
    uint64 elapsed = __tend.epoch_micro - __tstart.epoch_micro; \
    print_result(description, elapsed, TIMER_ITERATIONS); \
    }

class Benchmark : public ::zippylog::testing::TestBase
{ };

void print_result(string what, uint64 microseconds, uint64 ops)
{
    double seconds = (1.00 * microseconds) / 1000000.00;
    double rate = (1.00 * ops) / seconds;

    cout << what << " " << rate << "/s" << endl;
}

TEST_F(Benchmark, LuaFunctionCalls)
{
    lua_State *L = luaL_newstate();
    const char *function = "function test()\n    return nil\nend";
    assert(!luaL_loadstring(L, function));

    TIMER_START(1000000);
    lua_getglobal(L, "test");
    lua_pcall(L, 0, 1, 0);
    lua_pop(L, 1);
    TIMER_END("lua.pcall_empty_function");
}

void zmq_socket_send_recv(const char *address, int sender_type, int receiver_type, int message_size, int iterations, const char *name)
{
    ::zmq::context_t ctx(1);
    ::zmq::socket_t sender(ctx, sender_type);
    ::zmq::socket_t receiver(ctx, receiver_type);

    sender.bind(address);
    receiver.connect(address);

    TIMER_START(iterations);
    ::zmq::message_t msg(message_size);
    ::zmq::message_t received;

    sender.send(msg, NULL);
    receiver.recv(&received, NULL);
    TIMER_END(name);
}

TEST_F(Benchmark, ZeroMQ)
{
    TIMER_START(1000000);
    ::zmq::message_t *msg = new ::zmq::message_t();
    delete msg;
    TIMER_END("zmq.empty_message_allocation");

    TIMER_START(1000000);
    ::zmq::message_t *msg = new ::zmq::message_t(100);
    delete msg;
    TIMER_END("zmq.100_byte_message_allocation");

    TIMER_START(1000000);
    ::zmq::message_t *msg = new ::zmq::message_t(1000);
    delete msg;
    TIMER_END("zmq.1000_byte_message_allocation");

    TIMER_START(100000);
    ::zmq::message_t *msg = new ::zmq::message_t(10000);
    delete msg;
    TIMER_END("zmq.10000_byte_message_allocation");

    TIMER_START(10000);
    ::zmq::message_t *msg = new ::zmq::message_t(100000);
    delete msg;
    TIMER_END("zmq.100000_byte_message_allocation");

    zmq_socket_send_recv("inproc://00", ZMQ_PUSH, ZMQ_PULL, 0, 1000000, "zmq.socket.inproc.pushpull.empty");
    zmq_socket_send_recv("inproc://01", ZMQ_PUSH, ZMQ_PULL, 100, 1000000, "zmq.socket.inproc.pushpull.100_byte_message");
    zmq_socket_send_recv("inproc://02", ZMQ_PUSH, ZMQ_PULL, 1000, 1000000, "zmq.socket.inproc.pushpull.1000_byte_message");
    zmq_socket_send_recv("inproc://03", ZMQ_PUSH, ZMQ_PULL, 10000, 1000000, "zmq.socket.inproc.pushpull.10000_byte_message");
    zmq_socket_send_recv("inproc://04", ZMQ_PUSH, ZMQ_PULL, 100000, 100000, "zmq.socket.inproc.pushpull.100000_byte_message");
    zmq_socket_send_recv("inproc://05", ZMQ_PUSH, ZMQ_PULL, 1000000, 100000, "zmq.socket.inproc.pushpull.1000000_byte_message");
}

TEST_F(Benchmark, Envelope)
{
    TIMER_START(1000000);
    Envelope *e = new Envelope();
    delete e;
    TIMER_END("zippylog.envelope.empty_allocations");

    {
        Envelope e;
        string s;
        TIMER_START(1000000);
        e.Serialize(s);
        TIMER_END("zippylog.envelope.empty_serialize");
    }

    {
        Envelope e;
        ::zmq::message_t msg;
        TIMER_START(1000000);
        e.ToZmqMessage(msg);
        TIMER_END("zippylog.envelope.empty_zmq_serialize");
    }

    {
        Envelope e;
        ::zmq::message_t msg;
        TIMER_START(1000000);
        e.ToProtocolZmqMessage(msg);
        TIMER_END("zippylog.envelope.empty_zmq_protocol_serialize");
    }

    {
        Envelope empty;
        string serialized;
        empty.Serialize(serialized);
        void * buffer = (void *)serialized.data();
        int length = serialized.length();
        TIMER_START(1000000);
        Envelope e(buffer, length);
        TIMER_END("zippylog.envelope.empty_construct_from_buffer");
    }

    {
        Envelope empty;
        string serialized;
        empty.Serialize(serialized);
        TIMER_START(1000000);
        Envelope e(serialized);
        TIMER_END("zippylog.envelope.empty_construct_from_string");
    }

    {
        Envelope empty;
        ::zmq::message_t msg;
        empty.ToZmqMessage(msg);
        TIMER_START(1000000);
        Envelope e(msg);
        TIMER_END("zippylog.envelope.empty.construct_from_zmq");
    }

    {
        Envelope empty;
        TIMER_START(1000000);
        Envelope e(empty);
        TIMER_END("zippylog.envelope.empty_copy_constructor");
    }

    TIMER_START(1000000);
    Envelope e;
    ::zippylog::request_processor::Destroy msg;
    msg.add_to_envelope(e);
    TIMER_END("zippylog.envelope.create_and_add_message");
}

void client_ping_callback(Client *, void *data) {
    uint32 *i = (uint32 *)data;
    (*i)++;
}

/*
TEST_F(Benchmark, Server)
{
    ::zmq::context_t ctx(3);

    ServerStartParams start_params;
    start_params.ctx = &ctx;
    start_params.store_path = "simpledirectory://test/stores/00-simple";
    start_params.listen_endpoints.push_back("inproc://server00");
    start_params.log_bucket.clear();
    start_params.log_stream_set.clear();

    ::zippylog::device::Server server(start_params);
    server.RunAsync();

    {
        ::zmq::socket_t cs(ctx, ZMQ_REQ);
        cs.connect("inproc://server00");

        ::zippylog::protocol::request::PingV1 ping;
        Envelope e;
        ping.add_to_envelope(e);

        TIMER_START(100000);
        ::zmq::message_t msg;
        e.ToProtocolZmqMessage(msg);
        cs.send(msg, NULL);
        ::zmq::message_t response;
        cs.recv(&response, NULL);
        TIMER_END("zippylog.server.ping_request_reply");
    }

    {
        Client client(&ctx, "inproc://server00");
        int count = 0;

        TIMER_START(100000);
        client.Ping(client_ping_callback, (void *)&count);
        TIMER_END_WAIT("zippylog.server.ping_bulk_send", count);
    }

    server.Shutdown();
}
*/

TEST_F(Benchmark, LuaLoadString)
{
    LuaState l;
    string error;
    l.LoadLuaCode("function zippylog_load_string(s)\n"
                  "  e = zippylog.envelope.new()\n"
                  "  e:set_string_value(s)\n"
                  "  return e\n"
                  "end", error);

    ::zippylog::lua::LoadStringResult result;
    const string input = "foo bar 2k";
    TIMER_START(10000);
    l.ExecuteLoadString(input, result);
    TIMER_END("zippylog.lua.load_string_return_simple_envelope");
}

int main(int argc, char **argv)
{
    ::zippylog::initialize_library();

    ::testing::InitGoogleTest(&argc, argv);
    int result = RUN_ALL_TESTS();

    ::zippylog::shutdown_library();

    return result;
}
<commit_msg>add benchmark for testing envelope write speed<commit_after>//  Copyright 2011 Gregory Szorc
//
//  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 <zippylog/zippylog.hpp>
#include <zippylog/testing.hpp>

#include <zippylog/client.hpp>
#include <zippylog/envelope.hpp>
#include <zippylog/lua.hpp>
#include <zippylog/platform.hpp>
#include <zippylog/request_processor.pb.h>
#include <zippylog/store.hpp>
#include <zippylog/device/server.hpp>

extern "C" {
#include <lua.h>
#include <lauxlib.h>
}

#include <iostream>
#include <sstream>
#include <string>
#include <vector>

#include <assert.h>

using ::std::cerr;
using ::std::cout;
using ::std::endl;
using ::std::ostringstream;
using ::std::string;
using ::std::vector;
using ::zippylog::client::Client;
using ::zippylog::Envelope;
using ::zippylog::device::ServerStartParams;
using ::zippylog::lua::LuaState;
using ::zippylog::Store;

#define TIMER_START(iterations) { \
    int TIMER_ITERATIONS = iterations; \
    ::zippylog::platform::Time __tstart; \
    ::zippylog::platform::TimeNow(__tstart); \
    for (int TIMER_LOOP_VALUE = TIMER_ITERATIONS; TIMER_LOOP_VALUE; TIMER_LOOP_VALUE--) { \

#define TIMER_START_SINGLE() { \
    ::zippylog::platform::Time __tstart; \
    ::zippylog::platform::TimeNow(__tstart); { \

#define TIMER_END(description) } \
    ::zippylog::platform::Time __tend; \
    ::zippylog::platform::TimeNow(__tend); \
    uint64 elapsed = __tend.epoch_micro - __tstart.epoch_micro; \
    print_result(description, elapsed, TIMER_ITERATIONS); \
    }

#define TIMER_END_COUNT(description, count) } \
    ::zippylog::platform::Time __tend; \
    ::zippylog::platform::TimeNow(__tend); \
    uint64 elapsed = __tend.epoch_micro - __tstart.epoch_micro; \
    print_result(description, elapsed, count); \
    }

// this is like the one above except we take an int whose value
// we wait to go to the number of iterations
#define TIMER_END_WAIT(description, tracking) } \
    while (tracking != TIMER_ITERATIONS); \
    ::zippylog::platform::Time __tend; \
    ::zippylog::platform::TimeNow(__tend); \
    uint64 elapsed = __tend.epoch_micro - __tstart.epoch_micro; \
    print_result(description, elapsed, TIMER_ITERATIONS); \
    }

class Benchmark : public ::zippylog::testing::TestBase
{ };

void print_result(string what, uint64 microseconds, uint64 ops)
{
    double seconds = (1.00 * microseconds) / 1000000.00;
    double rate = (1.00 * ops) / seconds;

    cout << what << " " << rate << "/s" << endl;
}

TEST_F(Benchmark, LuaFunctionCalls)
{
    lua_State *L = luaL_newstate();
    const char *function = "function test()\n    return nil\nend";
    assert(!luaL_loadstring(L, function));

    TIMER_START(1000000);
    lua_getglobal(L, "test");
    lua_pcall(L, 0, 1, 0);
    lua_pop(L, 1);
    TIMER_END("lua.pcall_empty_function");
}

void zmq_socket_send_recv(const char *address, int sender_type, int receiver_type, int message_size, int iterations, const char *name)
{
    ::zmq::context_t ctx(1);
    ::zmq::socket_t sender(ctx, sender_type);
    ::zmq::socket_t receiver(ctx, receiver_type);

    sender.bind(address);
    receiver.connect(address);

    TIMER_START(iterations);
    ::zmq::message_t msg(message_size);
    ::zmq::message_t received;

    sender.send(msg, NULL);
    receiver.recv(&received, NULL);
    TIMER_END(name);
}

TEST_F(Benchmark, ZeroMQ)
{
    TIMER_START(1000000);
    ::zmq::message_t *msg = new ::zmq::message_t();
    delete msg;
    TIMER_END("zmq.empty_message_allocation");

    TIMER_START(1000000);
    ::zmq::message_t *msg = new ::zmq::message_t(100);
    delete msg;
    TIMER_END("zmq.100_byte_message_allocation");

    TIMER_START(1000000);
    ::zmq::message_t *msg = new ::zmq::message_t(1000);
    delete msg;
    TIMER_END("zmq.1000_byte_message_allocation");

    TIMER_START(100000);
    ::zmq::message_t *msg = new ::zmq::message_t(10000);
    delete msg;
    TIMER_END("zmq.10000_byte_message_allocation");

    TIMER_START(10000);
    ::zmq::message_t *msg = new ::zmq::message_t(100000);
    delete msg;
    TIMER_END("zmq.100000_byte_message_allocation");

    zmq_socket_send_recv("inproc://00", ZMQ_PUSH, ZMQ_PULL, 0, 1000000, "zmq.socket.inproc.pushpull.empty");
    zmq_socket_send_recv("inproc://01", ZMQ_PUSH, ZMQ_PULL, 100, 1000000, "zmq.socket.inproc.pushpull.100_byte_message");
    zmq_socket_send_recv("inproc://02", ZMQ_PUSH, ZMQ_PULL, 1000, 1000000, "zmq.socket.inproc.pushpull.1000_byte_message");
    zmq_socket_send_recv("inproc://03", ZMQ_PUSH, ZMQ_PULL, 10000, 1000000, "zmq.socket.inproc.pushpull.10000_byte_message");
    zmq_socket_send_recv("inproc://04", ZMQ_PUSH, ZMQ_PULL, 100000, 100000, "zmq.socket.inproc.pushpull.100000_byte_message");
    zmq_socket_send_recv("inproc://05", ZMQ_PUSH, ZMQ_PULL, 1000000, 100000, "zmq.socket.inproc.pushpull.1000000_byte_message");
}

TEST_F(Benchmark, Envelope)
{
    TIMER_START(1000000);
    Envelope *e = new Envelope();
    delete e;
    TIMER_END("zippylog.envelope.empty_allocations");

    {
        Envelope e;
        string s;
        TIMER_START(1000000);
        e.Serialize(s);
        TIMER_END("zippylog.envelope.empty_serialize");
    }

    {
        Envelope e;
        ::zmq::message_t msg;
        TIMER_START(1000000);
        e.ToZmqMessage(msg);
        TIMER_END("zippylog.envelope.empty_zmq_serialize");
    }

    {
        Envelope e;
        ::zmq::message_t msg;
        TIMER_START(1000000);
        e.ToProtocolZmqMessage(msg);
        TIMER_END("zippylog.envelope.empty_zmq_protocol_serialize");
    }

    {
        Envelope empty;
        string serialized;
        empty.Serialize(serialized);
        void * buffer = (void *)serialized.data();
        int length = serialized.length();
        TIMER_START(1000000);
        Envelope e(buffer, length);
        TIMER_END("zippylog.envelope.empty_construct_from_buffer");
    }

    {
        Envelope empty;
        string serialized;
        empty.Serialize(serialized);
        TIMER_START(1000000);
        Envelope e(serialized);
        TIMER_END("zippylog.envelope.empty_construct_from_string");
    }

    {
        Envelope empty;
        ::zmq::message_t msg;
        empty.ToZmqMessage(msg);
        TIMER_START(1000000);
        Envelope e(msg);
        TIMER_END("zippylog.envelope.empty.construct_from_zmq");
    }

    {
        Envelope empty;
        TIMER_START(1000000);
        Envelope e(empty);
        TIMER_END("zippylog.envelope.empty_copy_constructor");
    }

    TIMER_START(1000000);
    Envelope e;
    ::zippylog::request_processor::Destroy msg;
    msg.add_to_envelope(e);
    TIMER_END("zippylog.envelope.create_and_add_message");
}

void client_ping_callback(Client *, void *data) {
    uint32 *i = (uint32 *)data;
    (*i)++;
}

/*
TEST_F(Benchmark, Server)
{
    ::zmq::context_t ctx(3);

    ServerStartParams start_params;
    start_params.ctx = &ctx;
    start_params.store_path = "simpledirectory://test/stores/00-simple";
    start_params.listen_endpoints.push_back("inproc://server00");
    start_params.log_bucket.clear();
    start_params.log_stream_set.clear();

    ::zippylog::device::Server server(start_params);
    server.RunAsync();

    {
        ::zmq::socket_t cs(ctx, ZMQ_REQ);
        cs.connect("inproc://server00");

        ::zippylog::protocol::request::PingV1 ping;
        Envelope e;
        ping.add_to_envelope(e);

        TIMER_START(100000);
        ::zmq::message_t msg;
        e.ToProtocolZmqMessage(msg);
        cs.send(msg, NULL);
        ::zmq::message_t response;
        cs.recv(&response, NULL);
        TIMER_END("zippylog.server.ping_request_reply");
    }

    {
        Client client(&ctx, "inproc://server00");
        int count = 0;

        TIMER_START(100000);
        client.Ping(client_ping_callback, (void *)&count);
        TIMER_END_WAIT("zippylog.server.ping_bulk_send", count);
    }

    server.Shutdown();
}
*/

TEST_F(Benchmark, LuaLoadString)
{
    LuaState l;
    string error;
    l.LoadLuaCode("function zippylog_load_string(s)\n"
                  "  e = zippylog.envelope.new()\n"
                  "  e:set_string_value(s)\n"
                  "  return e\n"
                  "end", error);

    ::zippylog::lua::LoadStringResult result;
    const string input = "foo bar 2k";
    TIMER_START(10000);
    l.ExecuteLoadString(input, result);
    TIMER_END("zippylog.lua.load_string_return_simple_envelope");
}

TEST_F(Benchmark, StoreWriting)
{
    const int32 n = 1000000;

    Envelope *envelopes = new Envelope[n];
    for (int32 i = 0; i < n; i++) {
        envelopes[i] = this->GetRandomEnvelope();
    }

    Store * s = this->GetTemporaryStore();
    ASSERT_TRUE(s->CreateBucket("foo"));
    ASSERT_TRUE(s->CreateStreamset("foo", "bar"));

    TIMER_START_SINGLE();
    for (int32 i = 0; i < n; i++) {
        s->WriteEnvelope("foo", "bar", envelopes[i]);
    }
    TIMER_END_COUNT("zippylog.store.write_1M_envelopes", n);

    delete [] envelopes;
}

int main(int argc, char **argv)
{
    ::zippylog::initialize_library();

    ::testing::InitGoogleTest(&argc, argv);
    int result = RUN_ALL_TESTS();

    ::zippylog::shutdown_library();

    return result;
}
<|endoftext|>


<commit_before>#include <iostream>

int main(int argc, char *argv[])
{
    double x1;
    double y1;
    double x2;
    double y2;
    double m;
    double b;

    std::cout << "Enter x1: ";
    std::cin >> x1;

    std::cout << "Enter y1: " ;
    std::cin >>y1;

    std::cout << "Enter x2: ";
    std::cin >> x2;

    std::cout <<"Enter y2: " ;
    std::cin >> y2;

     // m =(y2-y1)/(x2-x1);
     // b = y1 - m*x1;

    if(y1 == y2)
    {
        std::cout << "y = " << y1 << std::endl;
    }
    else if(x1 == x2)
    {
        std::cout << "x = " << x1 << std::endl;
    }

   // cout << "The gradient of the line is :" << m << endl;
   // cout << "The intercept of the line is : " << b << endl;
   // cout << "The equation of the line is :" << "y =" << m << * "x"<< "+" << b << endl;

    return 0;
}
<commit_msg>closes partial<commit_after>#include <iostream>
#include <cmath>

int main(int argc, char *argv[])
{
    double x1;
    double y1;
    double x2;
    double y2;
    double m;
    double b;

    std::cout << "Enter x1: ";
    std::cin >> x1;

    std::cout << "Enter y1: " ;
    std::cin >>y1;

    std::cout << "Enter x2: ";
    std::cin >> x2;

    std::cout <<"Enter y2: " ;
    std::cin >> y2;

    if(y1 == y2)
    {
        std::cout << "y = " << y1 << std::endl;
    }
    else if(x1 == x2)
    {
        std::cout << "x = " << x1 << std::endl;
    }
    else
    {
        m = (y2-y1)/(x2-x1);
        b = y1 - m*x1;

        char operator ='+';
        if (b<0)
        {
            operator ='-';
            b = std::abs(b);
        }
     if( m == 1 && b==0)
         {
             std::cout << "y = x " <<std::endl;
         }
     else if( m == 1)
     {
         std::cout << " y = x+ " << b << std::endl;

     }
     else if(b==0)
     {
         std::cout << "y = x" * << m << std::endl;

     }
     else
     {
         std::cout << "y = " <<  m << * "x"<< " + " << b << std::endl;
     }

   }

    // std::cout << "The gradient of the line is :" << m << std::endl;
    // std::cout << "The intercept of the line is : " << b << std::endl;
    //std::cout << "The equation of the line is :" << "y =" << m << * "x"<< "+" << b << std::endl;

    return 0;
}
<|endoftext|>


<commit_before>// Copyright 2010-2012 University of Washington. All Rights Reserved.
// LICENSE_PLACEHOLDER
// This software was created with Government support under DE
// AC05-76RL01830 awarded by the United States Department of
// Energy. The Government has certain rights in the software.

#ifndef COLLECTIVE_HPP
#define COLLECTIVE_HPP

//#include "Grappa.hpp"
//#include "ForkJoin.hpp"
#include "common.hpp"
#include "CompletionEvent.hpp"
#include "Message.hpp"
#include "MessagePool.hpp"
#include "Tasking.hpp"
#include "FullEmpty.hpp"

#define COLL_MAX &collective_max
#define COLL_MIN &collective_min
#define COLL_ADD &collective_add
#define COLL_MULT &collective_mult

template< typename T >
T collective_add(const T& a, const T& b) {
  return a+b;
}
template< typename T >
T collective_max(const T& a, const T& b) {
  return (a>b) ? a : b;
}
template< typename T >
T collective_min(const T& a, const T& b) {
  return (a>b) ? a : b;
}
template< typename T >
T collective_mult(const T& a, const T& b) {
  return a*b;
}

#define HOME_NODE 0
extern Thread * reducing_thread;
extern Node reduction_reported_in;

// This class is just for holding the reduction
// value in a type-safe manner
template < typename T >
class Reductions {
  private:
    Reductions() {}
  public:
    static T reduction_result;
    static T final_reduction_result;
};

template <typename T>
T Reductions<T>::reduction_result;

template <typename T>
T Reductions<T>::final_reduction_result;

// wake the caller with the final reduction value set
template< typename T >
static void am_reduce_wake(T * val, size_t sz, void * payload, size_t psz) {
  Reductions<T>::final_reduction_result = *val;
  Grappa_wake(reducing_thread);
}

// wake the caller with the final reduction array value set
template< typename T >
static void am_reduce_array_wake(T * val, size_t sz, void * payload, size_t psz) {
  memcpy(Reductions<T*>::final_reduction_result, val, sz);
  Grappa_wake(reducing_thread);
}

// Grappa active message sent by every Node to HOME_NODE to perform reduction in one place
template< typename T, T (*Reducer)(const T&, const T&), T BaseVal>
static void am_reduce(T * val, size_t sz, void* payload, size_t psz) {
  CHECK(Grappa_mynode() == HOME_NODE);

  if (reduction_reported_in == 0) Reductions<T>::reduction_result = BaseVal;
  Reductions<T>::reduction_result = Reducer(Reductions<T>::reduction_result, *val);

  reduction_reported_in++;
  VLOG(5) << "reported_in = " << reduction_reported_in;
  if (reduction_reported_in == Grappa_nodes()) {
    reduction_reported_in = 0;
    for (Node n = 0; n < Grappa_nodes(); n++) {
      VLOG(5) << "waking " << n;
      T data = Reductions<T>::reduction_result;
      Grappa_call_on(n, &am_reduce_wake, &data);
    }
  }
}

// Grappa active message sent by every Node to HOME_NODE to perform reduction in one place
template< typename T, T (*Reducer)(const T&, const T&), T BaseVal>
static void am_reduce_array(T * val, size_t sz, void* payload, size_t psz) {
  CHECK(Grappa_mynode() == HOME_NODE);

  size_t nelem = sz / sizeof(T);

  if (reduction_reported_in == 0) {
    // allocate space for result
    Reductions<T*>::reduction_result = new T[nelem];
    for (size_t i=0; i<nelem; i++) Reductions<T*>::reduction_result[i] = BaseVal;
  }

  T * rarray = Reductions<T*>::reduction_result;
  for (size_t i=0; i<nelem; i++) {
    rarray[i] = Reducer(rarray[i], val[i]);
  }

  reduction_reported_in++;
  VLOG(5) << "reported_in = " << reduction_reported_in;
  if (reduction_reported_in == Grappa_nodes()) {
    reduction_reported_in = 0;
    for (Node n = 0; n < Grappa_nodes(); n++) {
      VLOG(5) << "waking " << n;
      Grappa_call_on(n, &am_reduce_array_wake, rarray, sizeof(T)*nelem);
    }
    delete [] Reductions<T*>::reduction_result;
  }
}

// am_reduce with no initial value
template< typename T, T (*Reducer)(const T&, const T&) >
static void am_reduce_noinit(T * val, size_t sz, void* payload, size_t psz) {
  CHECK(Grappa_mynode() == HOME_NODE);

  if (reduction_reported_in == 0) Reductions<T>::reduction_result = *val; // no base val
  else Reductions<T>::reduction_result = Reducer(Reductions<T>::reduction_result, *val);

  reduction_reported_in++;
  VLOG(5) << "reported_in = " << reduction_reported_in;
  if (reduction_reported_in == Grappa_nodes()) {
    reduction_reported_in = 0;
    for (Node n = 0; n < Grappa_nodes(); n++) {
      VLOG(5) << "waking " << n;
      T data = Reductions<T>::reduction_result;
      Grappa_call_on(n, &am_reduce_wake, &data);
    }
  }
}

/// Global reduction across all nodes, returning the completely reduced value to everyone.
/// Notes:
///  - this suffices as a global barrier across *all nodes*
///  - as such, only one instance of this can be running at a given time
///  - and it must be called by every node or deadlock will occur
///
/// @tparam T type of the reduced values
/// @tparam Reducer commutative and associative reduce function
/// @tparam BaseVal initial value, e.g. 0 for a sum
///
/// ALLNODES
template< typename T, T (*Reducer)(const T&, const T&), T BaseVal>
T Grappa_allreduce(T myval) {
  // TODO: do tree reduction to reduce amount of serialization at Node 0
  reducing_thread = CURRENT_THREAD;

  Grappa_call_on(HOME_NODE, &am_reduce<T,Reducer,BaseVal>, &myval);

  Grappa_suspend();

  return Reductions<T>::final_reduction_result;
}

// send one element for reduction
template< typename T, T (*Reducer)(const T&, const T&), T BaseVal>
void allreduce_one_message(T * array, size_t nelem, T * result = NULL) {
  const size_t maxn = 2048 / sizeof(T);
  CHECK( nelem <= maxn );
  // default is to overwrite original array
  if (!result) result = array;
  Reductions<T*>::final_reduction_result = result;

  // TODO: do tree reduction to reduce amount of serialization at Node 0
  reducing_thread = CURRENT_THREAD;

  Grappa_call_on(HOME_NODE, &am_reduce_array<T,Reducer,BaseVal>, array, sizeof(T)*nelem);
  Grappa_suspend();
}

/// Vector reduction.
/// That is, result[i] = node0.array[i] + node1.array[i] + ... + nodeN.array[i], for all i.
/// ALLNODES
template< typename T, T (*Reducer)(const T&, const T&), T BaseVal>
void Grappa_allreduce(T * array, size_t nelem, T * result = NULL) {
  const size_t maxn = 2048 / sizeof(T);

  for (size_t i=0; i<nelem; i+=maxn) {
    size_t n = MIN(maxn, nelem-i);
    allreduce_one_message<T,Reducer,BaseVal>(array+i, n, result);
  }
}

/// Global reduction across all nodes, returning the completely reduced value to everyone.
/// This variant uses no initial value for the reduction.
///
/// Notes:
///  - this suffices as a global barrier across *all nodes*
///  - as such, only one instance of this can be running at a given time
///  - and it must be called by every node or deadlock will occur
///
/// @tparam T type of the reduced values
/// @tparam Reducer commutative and associative reduce function
/// @tparam BaseVal initial value, e.g. 0 for a sum
///
/// ALLNODES
template< typename T, T (*Reducer)(const T&, const T&) >
T Grappa_allreduce_noinit(T myval) {
  // TODO: do tree reduction to reduce amount of serialization at Node 0
  reducing_thread = CURRENT_THREAD;

  Grappa_call_on(HOME_NODE, &am_reduce_noinit<T,Reducer>, &myval);

  Grappa_suspend();

  return Reductions<T>::final_reduction_result;
}

namespace Grappa {

  // Call message (work that cannot block) on all cores, block until ack received from all.
  template<typename F>
  void call_on_all_cores(F work) {
    MessagePool<(1<<16)> pool;

    CompletionEvent ce(Grappa::cores());
    auto ce_addr = make_global(&ce);

    for (Core c = 0; c < Grappa::cores(); c++) {
      pool.send_message(c, [ce_addr, work] {
        work();
        complete(ce_addr);
      });
    }
    ce.wait();
  }

  /// Spawn a private task on each core, block until all complete.
  /// To be used for any SPMD-style work (e.g. initializing globals).
  /// Also used as a primitive in Grappa system code where anything is done on all cores.
  template<typename F>
  void on_all_cores(F work) {
    MessagePool<(1<<16)> pool;

    CompletionEvent ce(Grappa::cores());
    auto ce_addr = make_global(&ce);

    for (Core c = 0; c < Grappa::cores(); c++) {
      pool.send_message(c, [ce_addr, work] {
        privateTask([ce_addr, work] {
          work();
          complete(ce_addr);
        });
      });
    }
    ce.wait();
  }

  namespace impl {

    template<typename T>
    struct Reduction {
      static FullEmpty<T> result;
    };
    template<typename T> FullEmpty<T> Reduction<T>::result;

    template< typename T, T (*ReduceOp)(const T&, const T&) >
    void collect_reduction(const T& val) {
      static T total;
      static Core cores_in = 0;

      CHECK(mycore() == HOME_NODE);

      if (cores_in == 0) {
        total = val;
      } else {
        total = ReduceOp(total, val);
      }

      cores_in++;
      DVLOG(4) << "cores_in: " << cores_in;

      if (cores_in == cores()) {
        cores_in = 0;
        T tmp_total = total;
        for (Core c = 0; c < cores(); c++) {
          send_heap_message(c, [tmp_total] {
            Reduction<T>::result.writeXF(tmp_total);
          });
        }
      }
    }

  }

  template< typename T, T (*ReduceOp)(const T&, const T&) >
  T allreduce(T myval) {
    impl::Reduction<T>::result.reset();

    send_message(HOME_NODE, [myval]{
      impl::collect_reduction<T,ReduceOp>(myval);
    });

    return impl::Reduction<T>::result.readFF();
  }

}

#endif // COLLECTIVE_HPP

<commit_msg>fix: send_heap_message because can't block in send_message.<commit_after>// Copyright 2010-2012 University of Washington. All Rights Reserved.
// LICENSE_PLACEHOLDER
// This software was created with Government support under DE
// AC05-76RL01830 awarded by the United States Department of
// Energy. The Government has certain rights in the software.

#ifndef COLLECTIVE_HPP
#define COLLECTIVE_HPP

//#include "Grappa.hpp"
//#include "ForkJoin.hpp"
#include "common.hpp"
#include "CompletionEvent.hpp"
#include "Message.hpp"
#include "MessagePool.hpp"
#include "Tasking.hpp"
#include "FullEmpty.hpp"

#define COLL_MAX &collective_max
#define COLL_MIN &collective_min
#define COLL_ADD &collective_add
#define COLL_MULT &collective_mult

template< typename T >
T collective_add(const T& a, const T& b) {
  return a+b;
}
template< typename T >
T collective_max(const T& a, const T& b) {
  return (a>b) ? a : b;
}
template< typename T >
T collective_min(const T& a, const T& b) {
  return (a>b) ? a : b;
}
template< typename T >
T collective_mult(const T& a, const T& b) {
  return a*b;
}

#define HOME_NODE 0
extern Thread * reducing_thread;
extern Node reduction_reported_in;

// This class is just for holding the reduction
// value in a type-safe manner
template < typename T >
class Reductions {
  private:
    Reductions() {}
  public:
    static T reduction_result;
    static T final_reduction_result;
};

template <typename T>
T Reductions<T>::reduction_result;

template <typename T>
T Reductions<T>::final_reduction_result;

// wake the caller with the final reduction value set
template< typename T >
static void am_reduce_wake(T * val, size_t sz, void * payload, size_t psz) {
  Reductions<T>::final_reduction_result = *val;
  Grappa_wake(reducing_thread);
}

// wake the caller with the final reduction array value set
template< typename T >
static void am_reduce_array_wake(T * val, size_t sz, void * payload, size_t psz) {
  memcpy(Reductions<T*>::final_reduction_result, val, sz);
  Grappa_wake(reducing_thread);
}

// Grappa active message sent by every Node to HOME_NODE to perform reduction in one place
template< typename T, T (*Reducer)(const T&, const T&), T BaseVal>
static void am_reduce(T * val, size_t sz, void* payload, size_t psz) {
  CHECK(Grappa_mynode() == HOME_NODE);

  if (reduction_reported_in == 0) Reductions<T>::reduction_result = BaseVal;
  Reductions<T>::reduction_result = Reducer(Reductions<T>::reduction_result, *val);

  reduction_reported_in++;
  VLOG(5) << "reported_in = " << reduction_reported_in;
  if (reduction_reported_in == Grappa_nodes()) {
    reduction_reported_in = 0;
    for (Node n = 0; n < Grappa_nodes(); n++) {
      VLOG(5) << "waking " << n;
      T data = Reductions<T>::reduction_result;
      Grappa_call_on(n, &am_reduce_wake, &data);
    }
  }
}

// Grappa active message sent by every Node to HOME_NODE to perform reduction in one place
template< typename T, T (*Reducer)(const T&, const T&), T BaseVal>
static void am_reduce_array(T * val, size_t sz, void* payload, size_t psz) {
  CHECK(Grappa_mynode() == HOME_NODE);

  size_t nelem = sz / sizeof(T);

  if (reduction_reported_in == 0) {
    // allocate space for result
    Reductions<T*>::reduction_result = new T[nelem];
    for (size_t i=0; i<nelem; i++) Reductions<T*>::reduction_result[i] = BaseVal;
  }

  T * rarray = Reductions<T*>::reduction_result;
  for (size_t i=0; i<nelem; i++) {
    rarray[i] = Reducer(rarray[i], val[i]);
  }

  reduction_reported_in++;
  VLOG(5) << "reported_in = " << reduction_reported_in;
  if (reduction_reported_in == Grappa_nodes()) {
    reduction_reported_in = 0;
    for (Node n = 0; n < Grappa_nodes(); n++) {
      VLOG(5) << "waking " << n;
      Grappa_call_on(n, &am_reduce_array_wake, rarray, sizeof(T)*nelem);
    }
    delete [] Reductions<T*>::reduction_result;
  }
}

// am_reduce with no initial value
template< typename T, T (*Reducer)(const T&, const T&) >
static void am_reduce_noinit(T * val, size_t sz, void* payload, size_t psz) {
  CHECK(Grappa_mynode() == HOME_NODE);

  if (reduction_reported_in == 0) Reductions<T>::reduction_result = *val; // no base val
  else Reductions<T>::reduction_result = Reducer(Reductions<T>::reduction_result, *val);

  reduction_reported_in++;
  VLOG(5) << "reported_in = " << reduction_reported_in;
  if (reduction_reported_in == Grappa_nodes()) {
    reduction_reported_in = 0;
    for (Node n = 0; n < Grappa_nodes(); n++) {
      VLOG(5) << "waking " << n;
      T data = Reductions<T>::reduction_result;
      Grappa_call_on(n, &am_reduce_wake, &data);
    }
  }
}

/// Global reduction across all nodes, returning the completely reduced value to everyone.
/// Notes:
///  - this suffices as a global barrier across *all nodes*
///  - as such, only one instance of this can be running at a given time
///  - and it must be called by every node or deadlock will occur
///
/// @tparam T type of the reduced values
/// @tparam Reducer commutative and associative reduce function
/// @tparam BaseVal initial value, e.g. 0 for a sum
///
/// ALLNODES
template< typename T, T (*Reducer)(const T&, const T&), T BaseVal>
T Grappa_allreduce(T myval) {
  // TODO: do tree reduction to reduce amount of serialization at Node 0
  reducing_thread = CURRENT_THREAD;

  Grappa_call_on(HOME_NODE, &am_reduce<T,Reducer,BaseVal>, &myval);

  Grappa_suspend();

  return Reductions<T>::final_reduction_result;
}

// send one element for reduction
template< typename T, T (*Reducer)(const T&, const T&), T BaseVal>
void allreduce_one_message(T * array, size_t nelem, T * result = NULL) {
  const size_t maxn = 2048 / sizeof(T);
  CHECK( nelem <= maxn );
  // default is to overwrite original array
  if (!result) result = array;
  Reductions<T*>::final_reduction_result = result;

  // TODO: do tree reduction to reduce amount of serialization at Node 0
  reducing_thread = CURRENT_THREAD;

  Grappa_call_on(HOME_NODE, &am_reduce_array<T,Reducer,BaseVal>, array, sizeof(T)*nelem);
  Grappa_suspend();
}

/// Vector reduction.
/// That is, result[i] = node0.array[i] + node1.array[i] + ... + nodeN.array[i], for all i.
/// ALLNODES
template< typename T, T (*Reducer)(const T&, const T&), T BaseVal>
void Grappa_allreduce(T * array, size_t nelem, T * result = NULL) {
  const size_t maxn = 2048 / sizeof(T);

  for (size_t i=0; i<nelem; i+=maxn) {
    size_t n = MIN(maxn, nelem-i);
    allreduce_one_message<T,Reducer,BaseVal>(array+i, n, result);
  }
}

/// Global reduction across all nodes, returning the completely reduced value to everyone.
/// This variant uses no initial value for the reduction.
///
/// Notes:
///  - this suffices as a global barrier across *all nodes*
///  - as such, only one instance of this can be running at a given time
///  - and it must be called by every node or deadlock will occur
///
/// @tparam T type of the reduced values
/// @tparam Reducer commutative and associative reduce function
/// @tparam BaseVal initial value, e.g. 0 for a sum
///
/// ALLNODES
template< typename T, T (*Reducer)(const T&, const T&) >
T Grappa_allreduce_noinit(T myval) {
  // TODO: do tree reduction to reduce amount of serialization at Node 0
  reducing_thread = CURRENT_THREAD;

  Grappa_call_on(HOME_NODE, &am_reduce_noinit<T,Reducer>, &myval);

  Grappa_suspend();

  return Reductions<T>::final_reduction_result;
}

namespace Grappa {

  // Call message (work that cannot block) on all cores, block until ack received from all.
  template<typename F>
  void call_on_all_cores(F work) {
    MessagePool<(1<<16)> pool;

    CompletionEvent ce(Grappa::cores());
    Core origin = mycore();

    for (Core c = 0; c < Grappa::cores(); c++) {
      pool.send_message(c, [&ce, origin, work] {
        work();
        send_heap_message(origin, [&ce]{ ce.complete(); });
      });
    }
    ce.wait();
  }

  /// Spawn a private task on each core, block until all complete.
  /// To be used for any SPMD-style work (e.g. initializing globals).
  /// Also used as a primitive in Grappa system code where anything is done on all cores.
  template<typename F>
  void on_all_cores(F work) {
    MessagePool<(1<<16)> pool;

    CompletionEvent ce(Grappa::cores());
    auto ce_addr = make_global(&ce);

    for (Core c = 0; c < Grappa::cores(); c++) {
      pool.send_message(c, [ce_addr, work] {
        privateTask([ce_addr, work] {
          work();
          complete(ce_addr);
        });
      });
    }
    ce.wait();
  }

  namespace impl {

    template<typename T>
    struct Reduction {
      static FullEmpty<T> result;
    };
    template<typename T> FullEmpty<T> Reduction<T>::result;

    template< typename T, T (*ReduceOp)(const T&, const T&) >
    void collect_reduction(const T& val) {
      static T total;
      static Core cores_in = 0;

      CHECK(mycore() == HOME_NODE);

      if (cores_in == 0) {
        total = val;
      } else {
        total = ReduceOp(total, val);
      }

      cores_in++;
      DVLOG(4) << "cores_in: " << cores_in;

      if (cores_in == cores()) {
        cores_in = 0;
        T tmp_total = total;
        for (Core c = 0; c < cores(); c++) {
          send_heap_message(c, [tmp_total] {
            Reduction<T>::result.writeXF(tmp_total);
          });
        }
      }
    }

  }

  template< typename T, T (*ReduceOp)(const T&, const T&) >
  T allreduce(T myval) {
    impl::Reduction<T>::result.reset();

    send_message(HOME_NODE, [myval]{
      impl::collect_reduction<T,ReduceOp>(myval);
    });

    return impl::Reduction<T>::result.readFF();
  }

}

#endif // COLLECTIVE_HPP

<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2009, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. 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.
 *
 * $Id$
 *
 */

#ifndef PCL_FEATURES_IMPL_RSD_H_
#define PCL_FEATURES_IMPL_RSD_H_

#include <cfloat>
#include "pcl/features/rsd.h"

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT, typename PointNT, typename PointOutT> Eigen::MatrixXf
pcl::computeRSD (boost::shared_ptr<const pcl::PointCloud<PointInT> > &surface, boost::shared_ptr<const pcl::PointCloud<PointNT> > &normals,
		 const std::vector<int> &indices, double max_dist,
		 int nr_subdiv, double plane_radius, PointOutT &radii, bool compute_histogram)
{
  Eigen::MatrixXf histogram;
  // Check if the full histogram has to be saved or not
  if (compute_histogram)
    histogram = Eigen::MatrixXf::Zero (nr_subdiv, nr_subdiv);

  // Initialize minimum and maximum angle values in each distance bin
  std::vector<std::vector<double> > min_max_angle_by_dist (nr_subdiv);
  min_max_angle_by_dist[0].resize (2);
  min_max_angle_by_dist[0][0] = min_max_angle_by_dist[0][1] = 0.0;
  for (int di=1; di<nr_subdiv; di++)
  {
    min_max_angle_by_dist[di].resize (2);
    min_max_angle_by_dist[di][0] = +DBL_MAX;
    min_max_angle_by_dist[di][1] = -DBL_MAX;
  }

  // Compute distance by normal angle distribution for points
  std::vector<int>::const_iterator i, begin (indices.begin()), end (indices.end());
  for(i = begin+1; i != end; ++i)
  {
    // compute angle between the two lines going through normals (disregard orientation!)
    double cosine = normals->points[*i].normal[0] * normals->points[*begin].normal[0] +
                    normals->points[*i].normal[1] * normals->points[*begin].normal[1] +
                    normals->points[*i].normal[2] * normals->points[*begin].normal[2];
    if (cosine > 1) cosine = 1;
    if (cosine < -1) cosine = -1;
    double angle  = acos (cosine);
    if (angle > M_PI/2) angle = M_PI - angle; /// \note: orientation is neglected!

    // Compute point to point distance
    double dist = sqrt ((surface->points[*i].x - surface->points[*begin].x) * (surface->points[*i].x - surface->points[*begin].x) +
                        (surface->points[*i].y - surface->points[*begin].y) * (surface->points[*i].y - surface->points[*begin].y) +
                        (surface->points[*i].z - surface->points[*begin].z) * (surface->points[*i].z - surface->points[*begin].z));

    if (dist > max_dist)
      continue; /// \note: we neglect points that are outside the specified interval!

    // compute bins and increase
    int bin_d = (int) floor (nr_subdiv * dist / max_dist);
    if (compute_histogram)
    {
      int bin_a = (int) floor (nr_subdiv * angle / (M_PI/2));
      histogram(bin_a, bin_d)++;
    }

    // update min-max values for distance bins
    if (min_max_angle_by_dist[bin_d][0] > angle) min_max_angle_by_dist[bin_d][0] = angle;
    if (min_max_angle_by_dist[bin_d][1] < angle) min_max_angle_by_dist[bin_d][1] = angle;
  }

  // Estimate radius from min and max lines
  double Amint_Amin = 0, Amint_d = 0;
  double Amaxt_Amax = 0, Amaxt_d = 0;
  for (int di=0; di<nr_subdiv; di++)
  {
    // combute the members of A'*A*r = A'*D
    if (min_max_angle_by_dist[di][1] >= 0)
    {
      double p_min = min_max_angle_by_dist[di][0];
      double p_max = min_max_angle_by_dist[di][1];
      double f = (di+0.5)*max_dist/nr_subdiv;
      Amint_Amin += p_min * p_min;
      Amint_d += p_min * f;
      Amaxt_Amax += p_max * p_max;
      Amaxt_d += p_max * f;
    }
  }
  float min_radius = Amint_Amin == 0 ? plane_radius : std::min (Amint_d/Amint_Amin, plane_radius);
  float max_radius = Amaxt_Amax == 0 ? plane_radius : std::min (Amaxt_d/Amaxt_Amax, plane_radius);

  // Small correction of the systematic error of the estimation (based on analysis with nr_subdiv_ = 5)
  min_radius *= 1.1;
  max_radius *= 0.9;
  if (min_radius < max_radius)
  {
    radii.r_min = min_radius;
    radii.r_max = max_radius;
  }
  else
  {
    radii.r_max = min_radius;
    radii.r_min = max_radius;
  }

  return histogram;
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT, typename PointOutT> Eigen::MatrixXf
pcl::computeRSD (boost::shared_ptr<const pcl::PointCloud<PointNT> > &normals,
		 const std::vector<int> &indices, const std::vector<float> &sqr_dists, double max_dist,
		 int nr_subdiv, double plane_radius, PointOutT &radii, bool compute_histogram)
{
  Eigen::MatrixXf histogram;
  // Check if the full histogram has to be saved or not
  if (compute_histogram)
    histogram = Eigen::MatrixXf::Zero (nr_subdiv, nr_subdiv);

  // Initialize minimum and maximum angle values in each distance bin
  std::vector<std::vector<double> > min_max_angle_by_dist (nr_subdiv);
  min_max_angle_by_dist[0].resize (2);
  min_max_angle_by_dist[0][0] = min_max_angle_by_dist[0][1] = 0.0;
  for (int di=1; di<nr_subdiv; di++)
  {
    min_max_angle_by_dist[di].resize (2);
    min_max_angle_by_dist[di][0] = +DBL_MAX;
    min_max_angle_by_dist[di][1] = -DBL_MAX;
  }

  // Compute distance by normal angle distribution for points
  std::vector<int>::const_iterator i, begin (indices.begin()), end (indices.end());
  for(i = begin+1; i != end; ++i)
  {
    // compute angle between the two lines going through normals (disregard orientation!)
    double cosine = normals->points[*i].normal[0] * normals->points[*begin].normal[0] +
                    normals->points[*i].normal[1] * normals->points[*begin].normal[1] +
                    normals->points[*i].normal[2] * normals->points[*begin].normal[2];
    if (cosine > 1) cosine = 1;
    if (cosine < -1) cosine = -1;
    double angle  = acos (cosine);
    if (angle > M_PI/2) angle = M_PI - angle; /// \note: orientation is neglected!

    // Compute point to point distance
    double dist = sqrt (sqr_dists[i-begin]);

    if (dist > max_dist)
      continue; /// \note: we neglect points that are outside the specified interval!

    // compute bins and increase
    int bin_d = (int) floor (nr_subdiv * dist / max_dist);
    if (compute_histogram)
    {
      int bin_a = (int) floor (nr_subdiv * angle / (M_PI/2));
      histogram(bin_a, bin_d)++;
    }

    // update min-max values for distance bins
    if (min_max_angle_by_dist[bin_d][0] > angle) min_max_angle_by_dist[bin_d][0] = angle;
    if (min_max_angle_by_dist[bin_d][1] < angle) min_max_angle_by_dist[bin_d][1] = angle;
  }

  // Estimate radius from min and max lines
  double Amint_Amin = 0, Amint_d = 0;
  double Amaxt_Amax = 0, Amaxt_d = 0;
  for (int di=0; di<nr_subdiv; di++)
  {
    // combute the members of A'*A*r = A'*D
    if (min_max_angle_by_dist[di][1] >= 0)
    {
      double p_min = min_max_angle_by_dist[di][0];
      double p_max = min_max_angle_by_dist[di][1];
      double f = (di+0.5)*max_dist/nr_subdiv;
      Amint_Amin += p_min * p_min;
      Amint_d += p_min * f;
      Amaxt_Amax += p_max * p_max;
      Amaxt_d += p_max * f;
    }
  }
  float min_radius = Amint_Amin == 0 ? plane_radius : std::min (Amint_d/Amint_Amin, plane_radius);
  float max_radius = Amaxt_Amax == 0 ? plane_radius : std::min (Amaxt_d/Amaxt_Amax, plane_radius);

  // Small correction of the systematic error of the estimation (based on analysis with nr_subdiv_ = 5)
  min_radius *= 1.1;
  max_radius *= 0.9;
  if (min_radius < max_radius)
  {
    radii.r_min = min_radius;
    radii.r_max = max_radius;
  }
  else
  {
    radii.r_max = min_radius;
    radii.r_min = max_radius;
  }

  return histogram;
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT, typename PointNT, typename PointOutT> void
pcl::RSDEstimation<PointInT, PointNT, PointOutT>::computeFeature (PointCloudOut &output)
{
  // Check if search_radius_ was set
  if (search_radius_ < 0)
  {
    PCL_ERROR ("[pcl::%s::computeFeature] A search radius needs to be set!\n", getClassName ().c_str ());
    output.width = output.height = 0;
    output.points.clear ();
    return;
  }

  // List of indices and corresponding squared distances for a neighborhood
  // \note resize is irrelevant for a radiusSearch ().
  std::vector<int> nn_indices;
  std::vector<float> nn_sqr_dists;

  // Check if the full histogram has to be saved or not
  if (save_histograms_)
  {
    // Reserve space for the output histogram dataset
    histograms_.reset (new std::vector<Eigen::MatrixXf>);
    histograms_->reserve (output.points.size ());

    // Iterating over the entire index vector
    for (size_t idx = 0; idx < indices_->size (); ++idx)
    {
      // Compute and store r_min and r_max in the output cloud
      this->searchForNeighbors ((*indices_)[idx], search_parameter_, nn_indices, nn_sqr_dists);
      //histograms_->push_back (computeRSD (surface_, normals_, nn_indices, search_radius_, nr_subdiv_, plane_radius_, output.points[idx], true));
      histograms_->push_back (computeRSD (normals_, nn_indices, nn_sqr_dists, search_radius_, nr_subdiv_, plane_radius_, output.points[idx], true));
    }
  }
  else
  {
    // Iterating over the entire index vector
    for (size_t idx = 0; idx < indices_->size (); ++idx)
    {
      // Compute and store r_min and r_max in the output cloud
      this->searchForNeighbors ((*indices_)[idx], search_parameter_, nn_indices, nn_sqr_dists);
      //computeRSD (surface_, normals_, nn_indices, search_radius_, nr_subdiv_, plane_radius_, output.points[idx], false);
      computeRSD (normals_, nn_indices, nn_sqr_dists, search_radius_, nr_subdiv_, plane_radius_, output.points[idx], false);
    }
  }
}

#define PCL_INSTANTIATE_RSDEstimation(T,NT,OutT) template class PCL_EXPORTS pcl::RSDEstimation<T,NT,OutT>;

#endif    // PCL_FEATURES_IMPL_VFH_H_
<commit_msg>Added check for RSD computation<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2009, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. 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.
 *
 * $Id$
 *
 */

#ifndef PCL_FEATURES_IMPL_RSD_H_
#define PCL_FEATURES_IMPL_RSD_H_

#include <cfloat>
#include "pcl/features/rsd.h"

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT, typename PointNT, typename PointOutT> Eigen::MatrixXf
pcl::computeRSD (boost::shared_ptr<const pcl::PointCloud<PointInT> > &surface, boost::shared_ptr<const pcl::PointCloud<PointNT> > &normals,
		 const std::vector<int> &indices, double max_dist,
		 int nr_subdiv, double plane_radius, PointOutT &radii, bool compute_histogram)
{
  // Check if the full histogram has to be saved or not
  Eigen::MatrixXf histogram;
  if (compute_histogram)
    histogram = Eigen::MatrixXf::Zero (nr_subdiv, nr_subdiv);

  // Check if enough points are provided or not
  if (indices.size () < 2)
  {
    radii.r_max = 0;
    radii.r_min = 0;
    return histogram;
  }

  // Initialize minimum and maximum angle values in each distance bin
  std::vector<std::vector<double> > min_max_angle_by_dist (nr_subdiv);
  min_max_angle_by_dist[0].resize (2);
  min_max_angle_by_dist[0][0] = min_max_angle_by_dist[0][1] = 0.0;
  for (int di=1; di<nr_subdiv; di++)
  {
    min_max_angle_by_dist[di].resize (2);
    min_max_angle_by_dist[di][0] = +DBL_MAX;
    min_max_angle_by_dist[di][1] = -DBL_MAX;
  }

  // Compute distance by normal angle distribution for points
  std::vector<int>::const_iterator i, begin (indices.begin()), end (indices.end());
  for(i = begin+1; i != end; ++i)
  {
    // compute angle between the two lines going through normals (disregard orientation!)
    double cosine = normals->points[*i].normal[0] * normals->points[*begin].normal[0] +
                    normals->points[*i].normal[1] * normals->points[*begin].normal[1] +
                    normals->points[*i].normal[2] * normals->points[*begin].normal[2];
    if (cosine > 1) cosine = 1;
    if (cosine < -1) cosine = -1;
    double angle  = acos (cosine);
    if (angle > M_PI/2) angle = M_PI - angle; /// \note: orientation is neglected!

    // Compute point to point distance
    double dist = sqrt ((surface->points[*i].x - surface->points[*begin].x) * (surface->points[*i].x - surface->points[*begin].x) +
                        (surface->points[*i].y - surface->points[*begin].y) * (surface->points[*i].y - surface->points[*begin].y) +
                        (surface->points[*i].z - surface->points[*begin].z) * (surface->points[*i].z - surface->points[*begin].z));

    if (dist > max_dist)
      continue; /// \note: we neglect points that are outside the specified interval!

    // compute bins and increase
    int bin_d = (int) floor (nr_subdiv * dist / max_dist);
    if (compute_histogram)
    {
      int bin_a = std::min (nr_subdiv-1, (int) floor (nr_subdiv * angle / (M_PI/2)));
      histogram(bin_a, bin_d)++;
    }

    // update min-max values for distance bins
    if (min_max_angle_by_dist[bin_d][0] > angle) min_max_angle_by_dist[bin_d][0] = angle;
    if (min_max_angle_by_dist[bin_d][1] < angle) min_max_angle_by_dist[bin_d][1] = angle;
  }

  // Estimate radius from min and max lines
  double Amint_Amin = 0, Amint_d = 0;
  double Amaxt_Amax = 0, Amaxt_d = 0;
  for (int di=0; di<nr_subdiv; di++)
  {
    // combute the members of A'*A*r = A'*D
    if (min_max_angle_by_dist[di][1] >= 0)
    {
      double p_min = min_max_angle_by_dist[di][0];
      double p_max = min_max_angle_by_dist[di][1];
      double f = (di+0.5)*max_dist/nr_subdiv;
      Amint_Amin += p_min * p_min;
      Amint_d += p_min * f;
      Amaxt_Amax += p_max * p_max;
      Amaxt_d += p_max * f;
    }
  }
  float min_radius = Amint_Amin == 0 ? plane_radius : std::min (Amint_d/Amint_Amin, plane_radius);
  float max_radius = Amaxt_Amax == 0 ? plane_radius : std::min (Amaxt_d/Amaxt_Amax, plane_radius);

  // Small correction of the systematic error of the estimation (based on analysis with nr_subdiv_ = 5)
  min_radius *= 1.1;
  max_radius *= 0.9;
  if (min_radius < max_radius)
  {
    radii.r_min = min_radius;
    radii.r_max = max_radius;
  }
  else
  {
    radii.r_max = min_radius;
    radii.r_min = max_radius;
  }

  return histogram;
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT, typename PointOutT> Eigen::MatrixXf
pcl::computeRSD (boost::shared_ptr<const pcl::PointCloud<PointNT> > &normals,
		 const std::vector<int> &indices, const std::vector<float> &sqr_dists, double max_dist,
		 int nr_subdiv, double plane_radius, PointOutT &radii, bool compute_histogram)
{
  // Check if the full histogram has to be saved or not
  Eigen::MatrixXf histogram;
  if (compute_histogram)
    histogram = Eigen::MatrixXf::Zero (nr_subdiv, nr_subdiv);

  // Check if enough points are provided or not
  if (indices.size () < 2)
  {
    radii.r_max = 0;
    radii.r_min = 0;
    return histogram;
  }

  // Initialize minimum and maximum angle values in each distance bin
  std::vector<std::vector<double> > min_max_angle_by_dist (nr_subdiv);
  min_max_angle_by_dist[0].resize (2);
  min_max_angle_by_dist[0][0] = min_max_angle_by_dist[0][1] = 0.0;
  for (int di=1; di<nr_subdiv; di++)
  {
    min_max_angle_by_dist[di].resize (2);
    min_max_angle_by_dist[di][0] = +DBL_MAX;
    min_max_angle_by_dist[di][1] = -DBL_MAX;
  }

  // Compute distance by normal angle distribution for points
  std::vector<int>::const_iterator i, begin (indices.begin()), end (indices.end());
  for(i = begin+1; i != end; ++i)
  {
    // compute angle between the two lines going through normals (disregard orientation!)
    double cosine = normals->points[*i].normal[0] * normals->points[*begin].normal[0] +
                    normals->points[*i].normal[1] * normals->points[*begin].normal[1] +
                    normals->points[*i].normal[2] * normals->points[*begin].normal[2];
    if (cosine > 1) cosine = 1;
    if (cosine < -1) cosine = -1;
    double angle  = acos (cosine);
    if (angle > M_PI/2) angle = M_PI - angle; /// \note: orientation is neglected!

    // Compute point to point distance
    double dist = sqrt (sqr_dists[i-begin]);

    if (dist > max_dist)
      continue; /// \note: we neglect points that are outside the specified interval!

    // compute bins and increase
    int bin_d = (int) floor (nr_subdiv * dist / max_dist);
    if (compute_histogram)
    {
      int bin_a = std::min (nr_subdiv-1, (int) floor (nr_subdiv * angle / (M_PI/2)));
      histogram(bin_a, bin_d)++;
    }

    // update min-max values for distance bins
    if (min_max_angle_by_dist[bin_d][0] > angle) min_max_angle_by_dist[bin_d][0] = angle;
    if (min_max_angle_by_dist[bin_d][1] < angle) min_max_angle_by_dist[bin_d][1] = angle;
  }

  // Estimate radius from min and max lines
  double Amint_Amin = 0, Amint_d = 0;
  double Amaxt_Amax = 0, Amaxt_d = 0;
  for (int di=0; di<nr_subdiv; di++)
  {
    // combute the members of A'*A*r = A'*D
    if (min_max_angle_by_dist[di][1] >= 0)
    {
      double p_min = min_max_angle_by_dist[di][0];
      double p_max = min_max_angle_by_dist[di][1];
      double f = (di+0.5)*max_dist/nr_subdiv;
      Amint_Amin += p_min * p_min;
      Amint_d += p_min * f;
      Amaxt_Amax += p_max * p_max;
      Amaxt_d += p_max * f;
    }
  }
  float min_radius = Amint_Amin == 0 ? plane_radius : std::min (Amint_d/Amint_Amin, plane_radius);
  float max_radius = Amaxt_Amax == 0 ? plane_radius : std::min (Amaxt_d/Amaxt_Amax, plane_radius);

  // Small correction of the systematic error of the estimation (based on analysis with nr_subdiv_ = 5)
  min_radius *= 1.1;
  max_radius *= 0.9;
  if (min_radius < max_radius)
  {
    radii.r_min = min_radius;
    radii.r_max = max_radius;
  }
  else
  {
    radii.r_max = min_radius;
    radii.r_min = max_radius;
  }

  return histogram;
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT, typename PointNT, typename PointOutT> void
pcl::RSDEstimation<PointInT, PointNT, PointOutT>::computeFeature (PointCloudOut &output)
{
  // Check if search_radius_ was set
  if (search_radius_ < 0)
  {
    PCL_ERROR ("[pcl::%s::computeFeature] A search radius needs to be set!\n", getClassName ().c_str ());
    output.width = output.height = 0;
    output.points.clear ();
    return;
  }

  // List of indices and corresponding squared distances for a neighborhood
  // \note resize is irrelevant for a radiusSearch ().
  std::vector<int> nn_indices;
  std::vector<float> nn_sqr_dists;

  // Check if the full histogram has to be saved or not
  if (save_histograms_)
  {
    // Reserve space for the output histogram dataset
    histograms_.reset (new std::vector<Eigen::MatrixXf>);
    histograms_->reserve (output.points.size ());

    // Iterating over the entire index vector
    for (size_t idx = 0; idx < indices_->size (); ++idx)
    {
      // Compute and store r_min and r_max in the output cloud
      this->searchForNeighbors ((*indices_)[idx], search_parameter_, nn_indices, nn_sqr_dists);
      //histograms_->push_back (computeRSD (surface_, normals_, nn_indices, search_radius_, nr_subdiv_, plane_radius_, output.points[idx], true));
      histograms_->push_back (computeRSD (normals_, nn_indices, nn_sqr_dists, search_radius_, nr_subdiv_, plane_radius_, output.points[idx], true));
    }
  }
  else
  {
    // Iterating over the entire index vector
    for (size_t idx = 0; idx < indices_->size (); ++idx)
    {
      // Compute and store r_min and r_max in the output cloud
      this->searchForNeighbors ((*indices_)[idx], search_parameter_, nn_indices, nn_sqr_dists);
      //computeRSD (surface_, normals_, nn_indices, search_radius_, nr_subdiv_, plane_radius_, output.points[idx], false);
      computeRSD (normals_, nn_indices, nn_sqr_dists, search_radius_, nr_subdiv_, plane_radius_, output.points[idx], false);
    }
  }
}

#define PCL_INSTANTIATE_RSDEstimation(T,NT,OutT) template class PCL_EXPORTS pcl::RSDEstimation<T,NT,OutT>;

#endif    // PCL_FEATURES_IMPL_VFH_H_
<|endoftext|>


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

#include <math.h>
#include <map>

#include "common/sedna.h"
#include "common/u/uutils.h"

#include "tr/crmutils/crmutils.h"
#include "tr/crmutils/crminternals.h"
#include "tr/structures/schema.h"
#include "tr/vmm/vmm.h"
#include "tr/pstr/pstrblk.h"
#include "tr/structures/metadata.h"
#include "tr/mo/mo.h"

#include "tr/structures/nodeoperations.h"
#include "tr/structures/nodeutils.h"
#include "tr/structures/nodeinterface.h"

using namespace internal;

/* predefined debug & error output stream */
se_stdlib_ostream crm_dbg(std::cerr);

/* some statistics counters */
struct debug_info
{
    long schema_count;
    long schema_str_count;
    long block_count;
    long block_fill;
    long inner_block_count;

    int64_t inner_block_fill;
    float inner_fill_percentage;
    float fill_percentage;
    int64_t node_count;
    int64_t ext_nid_count;
    int64_t str_size;
    long mdpth;           //max depth
    long cdp;             //current depth
};

static xptr
insertStatisticsInteger(xptr neighbour,const char* title, char* buf,int64_t count)
{
    xptr left=insert_element_i(neighbour,XNULL,XNULL,title,xs_untyped,NULL_XMLNS);
    u_i64toa(count,buf,10);
    insert_text_i(XNULL, XNULL, left, text_source_cstr(buf));
    return left;
}

static xptr
insertStatisticsDouble(xptr neighbour,const char* title, char* buf,double count)
{
    xptr left=insert_element_i(neighbour,XNULL,XNULL,title,xs_untyped,NULL_XMLNS);
    u_gcvt(count,10,buf);
    insert_text_i(XNULL, XNULL, left, text_source_cstr(buf));
    return left;
}

static void
insertNidAndStringsStatistics(xptr broot, xptr node)
{
    std::map<unsigned int,unsigned int> nidsz;
    std::map<unsigned int,unsigned int> strsz;
    std::map<schema_node_xptr,int> xsfo;
    std::map<schema_node_xptr,int> ncnt;
    std::vector<int> fo;
    int maxfo=0;
    int64_t midfo=0;
    unsigned int cnt=0;
    unsigned int strcnt=0;

    xptr root = broot;
    while (root!=XNULL)
    {
        xptr node = root;
        fo.push_back(0);
        while(node!=XNULL)
        {
            cnt++;
            //size count
            CHECKP(node);
            //scheme cnt
            schema_node_xptr sc = getSchemaPointer(node);
            std::map<schema_node_xptr,int>::iterator cit=ncnt.find(sc);
            if (cit!=ncnt.end())
            {
                ncnt[sc]++;
            }
            else
                ncnt[sc]=1;
            t_nid& nd= *(t_nid*) XADDR(nodeGetNIDPtr(node));
            int sz=(nd.size>0)?nd.size:*((shft*)(nd.prefix+sizeof(xptr)));
            if (nidsz.find(sz)==nidsz.end())
                nidsz[sz]=1;
            else
                nidsz[sz]++;
            //string cnt
            if (sc->has_text())
            {
                strcnt++;
                unsigned int strz = CommonTextNode(node).getTextSize();
                if (strsz.find(strz)==strsz.end())
                    strsz[strz]=1;
                else
                    strsz[strz]++;
            }
            //next node
            xptr tmp= getFirstChild(node);
            while (tmp==XNULL /*&& GETPARENTPOINTER(node)!=XNULL*/)
            {
                if (fo.back()>maxfo) maxfo=fo.back();
                midfo+=fo.back();
                schema_node_xptr scm =getSchemaPointer(node);
                std::map<schema_node_xptr,int>::iterator it=xsfo.find(scm);
                if (it!=xsfo.end())
                {
                    if (fo.back()>xsfo[scm]) xsfo[scm]=fo.back();
                }
                else
                    xsfo[scm]=fo.back();
                fo.pop_back();
                tmp = nodeGetRightSibling(node);
                if (tmp==XNULL)
                {
                    if (nodeGetParentIndirection(node)==XNULL)break;
                    node=nodeGetParent(node);
                    CHECKP(node);
                }
            }
            node=tmp;
            if(node!=XNULL)
            {
                fo.back()++;
                fo.push_back(0);
            }
        }
        root = getNextDescriptorOfSameSort(root);
    }

    xptr parent=insert_element_i(node,XNULL,XNULL,"NID",xs_untyped,NULL_XMLNS);
    char buf[20];
    u_itoa(maxfo,buf,10);
    xptr left=insert_attribute_i(XNULL,XNULL,parent,"max_fan_out",xs_untypedAtomic,buf,strlen(buf),NULL_XMLNS);
    u_gcvt((1.*midfo/cnt),10,buf);
    left=insert_attribute_i(left,XNULL,XNULL,"mid_fan_out",xs_untypedAtomic,buf,strlen(buf),NULL_XMLNS);

    //counting total Nid
    int64_t cnt_sz=0;
    int64_t cnt_out=0;
    unsigned int max=0;
    std::map<unsigned int,unsigned int>::const_iterator it=nidsz.begin();
    while (it!=nidsz.end())
    {
        cnt_sz+=it->second*it->first;
        if (it->first>11)
            cnt_out+=it->second*it->first;
        if (it->first>max) max=it->first;
        it++;
    }
    u_gcvt((cnt_sz/1024./1024.),10,buf);
    left=insert_attribute_i(left,XNULL,XNULL,"total_size",xs_untypedAtomic,buf,strlen(buf),NULL_XMLNS);
    u_gcvt((cnt_out/1024./1024.),10,buf);
    left=insert_attribute_i(left,XNULL,XNULL,"total_size_ext",xs_untypedAtomic,buf,strlen(buf),NULL_XMLNS);

    left=insert_element_i(left,XNULL,XNULL,"histogram",xs_untyped,NULL_XMLNS);
    xptr lf=XNULL;
    unsigned int i=1;
    for (i=1;i<=max;i++)
    {
        it=nidsz.find(i);
        if (it!=nidsz.end())
        {
            lf=insert_element_i(lf,XNULL,left,"bucket",xs_untyped,NULL_XMLNS);
            u_itoa(i,buf,10);
            xptr att=insert_attribute_i(XNULL,XNULL,lf,"size",xs_untypedAtomic,buf,strlen(buf),NULL_XMLNS);
            u_itoa(it->second,buf,10);
            att=insert_attribute_i(att,XNULL,XNULL,"total",xs_untypedAtomic,buf,strlen(buf),NULL_XMLNS);
            u_gcvt((100.*it->second/cnt),10,buf);
            insert_attribute_i(att,XNULL,XNULL,"percentage",xs_untypedAtomic,buf,strlen(buf),NULL_XMLNS);
        }
    }
    nidsz.clear();

    //counting total String
    cnt_sz=0;
    max=0;
    it=strsz.begin();
    while (it!=strsz.end())
    {
        cnt_sz+=it->second*it->first;
        if (it->first>max) max=it->first;
        it++;
    }
    parent=insert_element_i(parent,XNULL,XNULL,"STRINGS",xs_untyped,NULL_XMLNS);
    u_gcvt((cnt_sz/1024./1024.),10,buf);
    left=insert_attribute_i(XNULL,XNULL,parent,"total_size",xs_untypedAtomic,buf,strlen(buf),NULL_XMLNS);
    u_itoa(strcnt,buf,10);
    left=insert_attribute_i(left,XNULL,XNULL,"total_count",xs_untypedAtomic,buf,strlen(buf),NULL_XMLNS);
    left=insert_element_i(left,XNULL,XNULL,"histogram",xs_untyped,NULL_XMLNS);
    lf=XNULL;
    for (i=0;i<=max;i++)
    {
        it=strsz.find(i);
        if (it!=strsz.end())
        {
            lf=insert_element_i(lf,XNULL,left,"bucket",xs_untyped,NULL_XMLNS);
            u_itoa(i,buf,10);
            xptr att=insert_attribute_i(XNULL,XNULL,lf,"size",xs_untypedAtomic,buf,strlen(buf),NULL_XMLNS);
            u_itoa(it->second,buf,10);
            att=insert_attribute_i(att,XNULL,XNULL,"total",xs_untypedAtomic,buf,strlen(buf),NULL_XMLNS);
            u_gcvt((100.*it->second/strcnt),10,buf);
            insert_attribute_i(att,XNULL,XNULL,"percentage",xs_untypedAtomic,buf,strlen(buf),NULL_XMLNS);

        }
    }
    strsz.clear();
}

using namespace internal;

static void
getSimpleDebugInfo(schema_node_cptr snode, debug_info* d_in)
{
    d_in->schema_count++;
    if (snode->type!=element && snode->type!=xml_namespace)
        d_in->schema_str_count++;
    d_in->cdp++;
    xptr block = snode->bblk;

    while (block!=XNULL)
    {
        CHECKP(block);
        node_blk_hdr * blk = getBlockHeader(block);
        d_in->block_fill+=  blk->count*blk->dsc_size;
        d_in->block_count++;
        d_in->node_count+=blk->count;
        if (blk->nblk!=XNULL)
        {
            d_in->inner_block_fill+=blk->count*blk->dsc_size;
            d_in->inner_block_count++;
        }

        xptr node = getFirstBlockNode(block);
        while (node != XNULL) {
            d_in->ext_nid_count += nid_get_size(nodeGetNIDP(node));
            if (getNodeType(node) != element && getNodeType(node) != xml_namespace)
            {
                d_in->str_size += CommonTextNode(node).getTextSize();
            }
            node = nodeGetNext(node);
        }
        block=blk->nblk;
    }
    sc_ref_item* sc= snode->children->first;
    while (sc!=NULL)
    {
        getSimpleDebugInfo(sc->object.snode, d_in);
        sc=sc->next;
    }
    if (d_in->cdp>d_in->mdpth) d_in->mdpth=d_in->cdp;
    d_in->cdp--;
}

static inline void
error_msg(const char * ermsg,se_ostream& crmout)
{
    crmout << ermsg;
}

void getDebugInfo(schema_node_cptr snode, xptr& node)
{
    debug_info d_in = {};
    getSimpleDebugInfo(snode, (debug_info*)&d_in);
    d_in.fill_percentage=100.*d_in.block_fill/(d_in.block_count*(PAGE_SIZE-sizeof(node_blk_hdr)));
    d_in.inner_fill_percentage=100.*d_in.inner_block_fill/(d_in.inner_block_count*(PAGE_SIZE-sizeof(node_blk_hdr)));
    char buf[40];

    xptr left=insert_element_i(XNULL,XNULL,node,"total_schema_nodes",xs_untyped,NULL_XMLNS);
    u_itoa(d_in.schema_count,buf,10);
    insert_text_i(XNULL,XNULL,left, text_source_cstr(buf));

    left=insertStatisticsInteger(left,"total_schema_text_nodes",buf,d_in.schema_str_count);
    left=insertStatisticsInteger(left,"schema_depth",buf,d_in.mdpth);
    left=insertStatisticsInteger(left,"total_nodes",buf,d_in.node_count);
    left=insertStatisticsInteger(left,"total_desc_blk",buf,d_in.block_count);
    left=insertStatisticsDouble (left,"saturation",buf,d_in.fill_percentage);
    left=insertStatisticsDouble (left,"innr_blk_saturation",buf,d_in.inner_fill_percentage);
    left=insertStatisticsInteger(left,"total_innr_blk",buf,d_in.inner_block_count);
    left=insertStatisticsInteger(left,"total_innr_size",buf,d_in.inner_block_count*PAGE_SIZE);
    left=insertStatisticsDouble (left,"descriptor_size",buf,(0.0625*d_in.block_count));
    left=insertStatisticsDouble (left,"nids_size",buf,(0.00000095367431640625*d_in.ext_nid_count));

    left=insert_element_i(left,XNULL,XNULL,"distribution",xs_untyped,NULL_XMLNS);

    if (snode->bblk!=XNULL)
    {
        CHECKP(snode->bblk);
        insertNidAndStringsStatistics(getFirstBlockNode(snode->bblk), left);
    }
}

<commit_msg>Couple of obvious checkp added to getSimpleDebugInfo<commit_after>/*
* File:  debug_utils.cpp
* Copyright (C) 2004 The Institute for System Programming of the Russian Academy of Sciences (ISP RAS)
*/

#include <math.h>
#include <map>

#include "common/sedna.h"
#include "common/u/uutils.h"

#include "tr/crmutils/crmutils.h"
#include "tr/crmutils/crminternals.h"
#include "tr/structures/schema.h"
#include "tr/vmm/vmm.h"
#include "tr/pstr/pstrblk.h"
#include "tr/structures/metadata.h"
#include "tr/mo/mo.h"

#include "tr/structures/nodeoperations.h"
#include "tr/structures/nodeutils.h"
#include "tr/structures/nodeinterface.h"

using namespace internal;

/* predefined debug & error output stream */
se_stdlib_ostream crm_dbg(std::cerr);

/* some statistics counters */
struct debug_info
{
    long schema_count;
    long schema_str_count;
    long block_count;
    long block_fill;
    long inner_block_count;

    int64_t inner_block_fill;
    float inner_fill_percentage;
    float fill_percentage;
    int64_t node_count;
    int64_t ext_nid_count;
    int64_t str_size;
    long mdpth;           //max depth
    long cdp;             //current depth
};

static xptr
insertStatisticsInteger(xptr neighbour,const char* title, char* buf,int64_t count)
{
    xptr left=insert_element_i(neighbour,XNULL,XNULL,title,xs_untyped,NULL_XMLNS);
    u_i64toa(count,buf,10);
    insert_text_i(XNULL, XNULL, left, text_source_cstr(buf));
    return left;
}

static xptr
insertStatisticsDouble(xptr neighbour,const char* title, char* buf,double count)
{
    xptr left=insert_element_i(neighbour,XNULL,XNULL,title,xs_untyped,NULL_XMLNS);
    u_gcvt(count,10,buf);
    insert_text_i(XNULL, XNULL, left, text_source_cstr(buf));
    return left;
}

static void
insertNidAndStringsStatistics(xptr broot, xptr node)
{
    std::map<unsigned int,unsigned int> nidsz;
    std::map<unsigned int,unsigned int> strsz;
    std::map<schema_node_xptr,int> xsfo;
    std::map<schema_node_xptr,int> ncnt;
    std::vector<int> fo;
    int maxfo=0;
    int64_t midfo=0;
    unsigned int cnt=0;
    unsigned int strcnt=0;

    xptr root = broot;
    while (root!=XNULL)
    {
        xptr node = root;
        fo.push_back(0);
        while(node!=XNULL)
        {
            cnt++;
            //size count
            CHECKP(node);
            //scheme cnt
            schema_node_xptr sc = getSchemaPointer(node);
            std::map<schema_node_xptr,int>::iterator cit=ncnt.find(sc);
            if (cit!=ncnt.end())
            {
                ncnt[sc]++;
            }
            else
                ncnt[sc]=1;
            t_nid& nd= *(t_nid*) XADDR(nodeGetNIDPtr(node));
            int sz=(nd.size>0)?nd.size:*((shft*)(nd.prefix+sizeof(xptr)));
            if (nidsz.find(sz)==nidsz.end())
                nidsz[sz]=1;
            else
                nidsz[sz]++;
            //string cnt
            if (sc->has_text())
            {
                strcnt++;
                unsigned int strz = CommonTextNode(node).getTextSize();
                if (strsz.find(strz)==strsz.end())
                    strsz[strz]=1;
                else
                    strsz[strz]++;
            }
            //next node
            xptr tmp= getFirstChild(node);
            while (tmp==XNULL /*&& GETPARENTPOINTER(node)!=XNULL*/)
            {
                if (fo.back()>maxfo) maxfo=fo.back();
                midfo+=fo.back();
                schema_node_xptr scm =getSchemaPointer(node);
                std::map<schema_node_xptr,int>::iterator it=xsfo.find(scm);
                if (it!=xsfo.end())
                {
                    if (fo.back()>xsfo[scm]) xsfo[scm]=fo.back();
                }
                else
                    xsfo[scm]=fo.back();
                fo.pop_back();
                tmp = nodeGetRightSibling(node);
                if (tmp==XNULL)
                {
                    if (nodeGetParentIndirection(node)==XNULL)break;
                    node=nodeGetParent(node);
                    CHECKP(node);
                }
            }
            node=tmp;
            if(node!=XNULL)
            {
                fo.back()++;
                fo.push_back(0);
            }
        }
        root = getNextDescriptorOfSameSort(root);
    }

    xptr parent=insert_element_i(node,XNULL,XNULL,"NID",xs_untyped,NULL_XMLNS);
    char buf[20];
    u_itoa(maxfo,buf,10);
    xptr left=insert_attribute_i(XNULL,XNULL,parent,"max_fan_out",xs_untypedAtomic,buf,strlen(buf),NULL_XMLNS);
    u_gcvt((1.*midfo/cnt),10,buf);
    left=insert_attribute_i(left,XNULL,XNULL,"mid_fan_out",xs_untypedAtomic,buf,strlen(buf),NULL_XMLNS);

    //counting total Nid
    int64_t cnt_sz=0;
    int64_t cnt_out=0;
    unsigned int max=0;
    std::map<unsigned int,unsigned int>::const_iterator it=nidsz.begin();
    while (it!=nidsz.end())
    {
        cnt_sz+=it->second*it->first;
        if (it->first>11)
            cnt_out+=it->second*it->first;
        if (it->first>max) max=it->first;
        it++;
    }
    u_gcvt((cnt_sz/1024./1024.),10,buf);
    left=insert_attribute_i(left,XNULL,XNULL,"total_size",xs_untypedAtomic,buf,strlen(buf),NULL_XMLNS);
    u_gcvt((cnt_out/1024./1024.),10,buf);
    left=insert_attribute_i(left,XNULL,XNULL,"total_size_ext",xs_untypedAtomic,buf,strlen(buf),NULL_XMLNS);

    left=insert_element_i(left,XNULL,XNULL,"histogram",xs_untyped,NULL_XMLNS);
    xptr lf=XNULL;
    unsigned int i=1;
    for (i=1;i<=max;i++)
    {
        it=nidsz.find(i);
        if (it!=nidsz.end())
        {
            lf=insert_element_i(lf,XNULL,left,"bucket",xs_untyped,NULL_XMLNS);
            u_itoa(i,buf,10);
            xptr att=insert_attribute_i(XNULL,XNULL,lf,"size",xs_untypedAtomic,buf,strlen(buf),NULL_XMLNS);
            u_itoa(it->second,buf,10);
            att=insert_attribute_i(att,XNULL,XNULL,"total",xs_untypedAtomic,buf,strlen(buf),NULL_XMLNS);
            u_gcvt((100.*it->second/cnt),10,buf);
            insert_attribute_i(att,XNULL,XNULL,"percentage",xs_untypedAtomic,buf,strlen(buf),NULL_XMLNS);
        }
    }
    nidsz.clear();

    //counting total String
    cnt_sz=0;
    max=0;
    it=strsz.begin();
    while (it!=strsz.end())
    {
        cnt_sz+=it->second*it->first;
        if (it->first>max) max=it->first;
        it++;
    }
    parent=insert_element_i(parent,XNULL,XNULL,"STRINGS",xs_untyped,NULL_XMLNS);
    u_gcvt((cnt_sz/1024./1024.),10,buf);
    left=insert_attribute_i(XNULL,XNULL,parent,"total_size",xs_untypedAtomic,buf,strlen(buf),NULL_XMLNS);
    u_itoa(strcnt,buf,10);
    left=insert_attribute_i(left,XNULL,XNULL,"total_count",xs_untypedAtomic,buf,strlen(buf),NULL_XMLNS);
    left=insert_element_i(left,XNULL,XNULL,"histogram",xs_untyped,NULL_XMLNS);
    lf=XNULL;
    for (i=0;i<=max;i++)
    {
        it=strsz.find(i);
        if (it!=strsz.end())
        {
            lf=insert_element_i(lf,XNULL,left,"bucket",xs_untyped,NULL_XMLNS);
            u_itoa(i,buf,10);
            xptr att=insert_attribute_i(XNULL,XNULL,lf,"size",xs_untypedAtomic,buf,strlen(buf),NULL_XMLNS);
            u_itoa(it->second,buf,10);
            att=insert_attribute_i(att,XNULL,XNULL,"total",xs_untypedAtomic,buf,strlen(buf),NULL_XMLNS);
            u_gcvt((100.*it->second/strcnt),10,buf);
            insert_attribute_i(att,XNULL,XNULL,"percentage",xs_untypedAtomic,buf,strlen(buf),NULL_XMLNS);

        }
    }
    strsz.clear();
}

using namespace internal;

static void
getSimpleDebugInfo(schema_node_cptr snode, debug_info* d_in)
{
    d_in->schema_count++;
    if (snode->type!=element && snode->type!=xml_namespace)
        d_in->schema_str_count++;
    d_in->cdp++;
    xptr block = snode->bblk;

    while (block!=XNULL)
    {
        CHECKP(block);
        node_blk_hdr * blk = getBlockHeader(block);
        d_in->block_fill+=  blk->count*blk->dsc_size;
        d_in->block_count++;
        d_in->node_count+=blk->count;
        if (blk->nblk!=XNULL)
        {
            d_in->inner_block_fill+=blk->count*blk->dsc_size;
            d_in->inner_block_count++;
        }

        xptr node = getFirstBlockNode(block);
        while (node != XNULL) {
            d_in->ext_nid_count += nid_get_size(nodeGetNIDP(node));
            CHECKP(node);
            if (getNodeType(node) != element && getNodeType(node) != xml_namespace)
            {
                d_in->str_size += CommonTextNode(node).getTextSize();
                CHECKP(node);
            }
            node = nodeGetNext(node);
        }
        block=blk->nblk;
    }
    sc_ref_item* sc= snode->children->first;
    while (sc!=NULL)
    {
        getSimpleDebugInfo(sc->object.snode, d_in);
        sc=sc->next;
    }
    if (d_in->cdp>d_in->mdpth) d_in->mdpth=d_in->cdp;
    d_in->cdp--;
}

static inline void
error_msg(const char * ermsg,se_ostream& crmout)
{
    crmout << ermsg;
}

void getDebugInfo(schema_node_cptr snode, xptr& node)
{
    debug_info d_in = {};
    getSimpleDebugInfo(snode, (debug_info*)&d_in);
    d_in.fill_percentage=100.*d_in.block_fill/(d_in.block_count*(PAGE_SIZE-sizeof(node_blk_hdr)));
    d_in.inner_fill_percentage=100.*d_in.inner_block_fill/(d_in.inner_block_count*(PAGE_SIZE-sizeof(node_blk_hdr)));
    char buf[40];

    xptr left=insert_element_i(XNULL,XNULL,node,"total_schema_nodes",xs_untyped,NULL_XMLNS);
    u_itoa(d_in.schema_count,buf,10);
    insert_text_i(XNULL,XNULL,left, text_source_cstr(buf));

    left=insertStatisticsInteger(left,"total_schema_text_nodes",buf,d_in.schema_str_count);
    left=insertStatisticsInteger(left,"schema_depth",buf,d_in.mdpth);
    left=insertStatisticsInteger(left,"total_nodes",buf,d_in.node_count);
    left=insertStatisticsInteger(left,"total_desc_blk",buf,d_in.block_count);
    left=insertStatisticsDouble (left,"saturation",buf,d_in.fill_percentage);
    left=insertStatisticsDouble (left,"innr_blk_saturation",buf,d_in.inner_fill_percentage);
    left=insertStatisticsInteger(left,"total_innr_blk",buf,d_in.inner_block_count);
    left=insertStatisticsInteger(left,"total_innr_size",buf,d_in.inner_block_count*PAGE_SIZE);
    left=insertStatisticsDouble (left,"descriptor_size",buf,(0.0625*d_in.block_count));
    left=insertStatisticsDouble (left,"nids_size",buf,(0.00000095367431640625*d_in.ext_nid_count));

    left=insert_element_i(left,XNULL,XNULL,"distribution",xs_untyped,NULL_XMLNS);

    if (snode->bblk!=XNULL)
    {
        CHECKP(snode->bblk);
        insertNidAndStringsStatistics(getFirstBlockNode(snode->bblk), left);
    }
}

<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * This file is part of the libkeynote project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <cmath>

#include "KNObject.h"
#include "KNPath.h"
#include "KNShape.h"
#include "KNTypes.h"

#include "KNShapeTest.h"

namespace test
{

using libkeynote::KNPath;
using libkeynote::KNPathPtr_t;
using libkeynote::KNSize;

void KNShapeTest::setUp()
{
}

void KNShapeTest::tearDown()
{
}

void KNShapeTest::testMakePolygonPath()
{
  using libkeynote::makePolygonPath;

  const KNSize size(100, 100);

  // triangle
  {
    KNPath ref;
    ref.appendMoveTo(50, 0);
    ref.appendLineTo(100, 100);
    ref.appendLineTo(0, 100);
    ref.appendClose();

    const KNPathPtr_t test = makePolygonPath(size, 3);

    CPPUNIT_ASSERT(bool(test));
    CPPUNIT_ASSERT(*test == ref);
  }

  // diamond
  {
    KNPath ref;
    ref.appendMoveTo(50, 0);
    ref.appendLineTo(100, 50);
    ref.appendLineTo(50, 100);
    ref.appendLineTo(0, 50);
    ref.appendClose();

    const KNPathPtr_t test = makePolygonPath(size, 4);

    CPPUNIT_ASSERT(bool(test));
    CPPUNIT_ASSERT(*test == ref);
  }

  // octagon
  {
    const double d = 100 * (1 - M_SQRT2);

    KNPath ref;
    ref.appendMoveTo(50, 0);
    ref.appendLineTo(100 - d, d);
    ref.appendLineTo(100, 50);
    ref.appendLineTo(100 - d, 100 -d);
    ref.appendLineTo(50, 100);
    ref.appendLineTo(d, 100 - d);
    ref.appendLineTo(0, 50);
    ref.appendLineTo(d, d);
    ref.appendClose();

    const KNPathPtr_t test = makePolygonPath(size, 8);

    CPPUNIT_ASSERT(bool(test));
    CPPUNIT_ASSERT(*test == ref);
  }
}

void KNShapeTest::testMakeRoundedRectanglePath()
{
  // TODO: implement me
}

void KNShapeTest::testMakeArrowPath()
{
  // TODO: implement me
}

void KNShapeTest::testMakeDoubleArrowPath()
{
  // TODO: implement me
}

void KNShapeTest::testMakeStarPath()
{
  // TODO: implement me
}

void KNShapeTest::testMakeConnectionPath()
{
  // TODO: implement me
}

void KNShapeTest::testMakeCalloutPath()
{
  // TODO: implement me
}

void KNShapeTest::testMakeQuoteBubblePath()
{
  // TODO: implement me
}

CPPUNIT_TEST_SUITE_REGISTRATION(KNShapeTest);

}

/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
<commit_msg>temporarily disable test<commit_after>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * This file is part of the libkeynote project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <cmath>

#include "KNObject.h"
#include "KNPath.h"
#include "KNShape.h"
#include "KNTypes.h"

#include "KNShapeTest.h"

namespace test
{

using libkeynote::KNPath;
using libkeynote::KNPathPtr_t;
using libkeynote::KNSize;

void KNShapeTest::setUp()
{
}

void KNShapeTest::tearDown()
{
}

void KNShapeTest::testMakePolygonPath()
{
  using libkeynote::makePolygonPath;

  const KNSize size(100, 100);

  // triangle
  {
    KNPath ref;
    ref.appendMoveTo(50, 0);
    ref.appendLineTo(100, 100);
    ref.appendLineTo(0, 100);
    ref.appendClose();

    const KNPathPtr_t test = makePolygonPath(size, 3);

    CPPUNIT_ASSERT(bool(test));
    CPPUNIT_ASSERT(*test == ref);
  }

  // diamond
  {
    KNPath ref;
    ref.appendMoveTo(50, 0);
    ref.appendLineTo(100, 50);
    ref.appendLineTo(50, 100);
    ref.appendLineTo(0, 50);
    ref.appendClose();

    const KNPathPtr_t test = makePolygonPath(size, 4);

    CPPUNIT_ASSERT(bool(test));
    CPPUNIT_ASSERT(*test == ref);
  }

  // octagon
  {
    const double d = 100 * (1 - M_SQRT2);

    KNPath ref;
    ref.appendMoveTo(50, 0);
    ref.appendLineTo(100 - d, d);
    ref.appendLineTo(100, 50);
    ref.appendLineTo(100 - d, 100 -d);
    ref.appendLineTo(50, 100);
    ref.appendLineTo(d, 100 - d);
    ref.appendLineTo(0, 50);
    ref.appendLineTo(d, d);
    ref.appendClose();

    const KNPathPtr_t test = makePolygonPath(size, 8);

    CPPUNIT_ASSERT(bool(test));
    CPPUNIT_ASSERT(*test == ref);
  }
}

void KNShapeTest::testMakeRoundedRectanglePath()
{
  // TODO: implement me
}

void KNShapeTest::testMakeArrowPath()
{
  // TODO: implement me
}

void KNShapeTest::testMakeDoubleArrowPath()
{
  // TODO: implement me
}

void KNShapeTest::testMakeStarPath()
{
  // TODO: implement me
}

void KNShapeTest::testMakeConnectionPath()
{
  // TODO: implement me
}

void KNShapeTest::testMakeCalloutPath()
{
  // TODO: implement me
}

void KNShapeTest::testMakeQuoteBubblePath()
{
  // TODO: implement me
}

// FIXME: enable
// CPPUNIT_TEST_SUITE_REGISTRATION(KNShapeTest);

}

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


<commit_before>/*************************************************************************
*    UrBackup - Client/Server backup system
*    Copyright (C) 2011-2016 Martin Raiber
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU Affero General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    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 General Public License for more details.
*
*    You should have received a copy of the GNU Affero General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/

#include "../Interface/Database.h"
#include "../Interface/Server.h"
#include "../Interface/DatabaseCursor.h"
#include "database.h"
#include "server_settings.h"
#include "LMDBFileIndex.h"
#include "../stringtools.h"
#include "../urbackupcommon/os_functions.h"
#include "serverinterface/helper.h"
#include "dao/ServerBackupDao.h"

namespace
{

struct SCallbackData
{
	IDatabaseCursor* cur;
	int64 pos;
	int64 max_pos;
	SStartupStatus* status;
};

db_results create_callback(size_t n_done, size_t n_rows, void *userdata)
{
	SCallbackData *data=(SCallbackData*)userdata;

	data->status->processed_file_entries=n_done;

	int last_pc = static_cast<int>(data->status->pc_done*1000 + 0.5);

	if(data->max_pos>0)
	{
		data->status->pc_done = static_cast<double>(n_rows)/data->max_pos;
	}

	int curr_pc = static_cast<int>(data->status->pc_done*1000 + 0.5);

	if(curr_pc!=last_pc)
	{
		Server->Log("Creating files index: "+convert((double)curr_pc/10)+"% finished", LL_INFO);
	}

	db_results ret;
	db_single_result res;

	if(data->cur->next(res))
	{
		ret.push_back(res);
	}

	return ret;
}

bool create_files_index_common(FileIndex& fileindex, SStartupStatus& status)
{
	IDatabase *db=Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER);

	db_results cache_res;
	if(db->getEngineName()=="sqlite")
	{
		cache_res=db->Read("PRAGMA cache_size");
		ServerSettings server_settings(db);
		db->Write("PRAGMA cache_size = -"+convert(server_settings.getSettings()->update_stats_cachesize));

		Server->Log("Transitioning urbackup server database to different journaling mode...", LL_INFO);
		db->Write("PRAGMA journal_mode = DELETE");
	}

	status.creating_filesindex=true;
	Server->Log("Creating file entry index. This might take a while...", LL_WARNING);

	Server->Log("Getting number of files...", LL_INFO);

	db_results res = db->Read("SELECT COUNT(*) AS c FROM files");

	int64 n_files = 0;
	if(!res.empty())
	{
		n_files=watoi64(res[0]["c"]);
	}

	db->BeginWriteTransaction();

	Server->Log("Starting creating files index...", LL_INFO);

	IQuery *q_read=db->Prepare("SELECT id, shahash, filesize, clientid, next_entry, prev_entry, pointed_to FROM files ORDER BY shahash ASC, filesize ASC, clientid ASC, created DESC");

	SCallbackData data;
	data.cur=q_read->Cursor();
	data.pos=0;
	data.max_pos=n_files;
	data.status=&status;

	fileindex.create(create_callback, &data);

	if(fileindex.has_error())
	{
		db->Write("ROLLBACK");
		return false;
	}
	else
	{
		db->EndTransaction();
	}

	if(!cache_res.empty())
	{
		db->Write("PRAGMA cache_size = "+cache_res[0]["cache_size"]);
		db->Write("PRAGMA shrink_memory");
		db->Write("PRAGMA journal_mode = WAL");
	}

	status.creating_filesindex=false;

	if(data.cur->has_error())
	{
		return false;
	}

	return true;
}

bool setup_lmdb_file_index(SStartupStatus& status)
{
	LMDBFileIndex fileindex(true);;
	if(fileindex.has_error())
	{
		Server->Log("Error creating file index", LL_ERROR);
		return false;
	}

	return create_files_index_common(fileindex, status);
}

}

void delete_file_index(void)
{
	Server->deleteFile("urbackup/fileindex/backup_server_files_index.lmdb");
	Server->deleteFile("urbackup/fileindex/backup_server_files_index.lmdb-lock");
}

bool create_files_index(SStartupStatus& status)
{
	IDatabase *db=Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER);
	ServerSettings settings(db);

	ServerBackupDao backupdao(db);

	bool creating_index = backupdao.getMiscValue("creating_file_entry_index").value=="true";

	if(!FileExists("urbackup/fileindex/backup_server_files_index.lmdb") || creating_index)
	{
		delete_file_index();

		{
			DBScopedSynchronous synchronous_db(db);

			backupdao.delMiscValue("creating_file_entry_index");
			backupdao.addMiscValue("creating_file_entry_index", "true");
		}

		status.upgrading_database=false;
		status.creating_filesindex=true;

		if(!setup_lmdb_file_index(status))
		{
			Server->Log("Setting up file index failed", LL_ERROR);
			return false;
		}
		else
		{
			backupdao.delMiscValue("creating_file_entry_index");
		}
	}

	LMDBFileIndex::initFileIndex();

	return true;

}

FileIndex* create_lmdb_files_index(void)
{
	if(!FileExists("urbackup/fileindex/backup_server_files_index.lmdb"))
	{
		return NULL;
	}

	return new LMDBFileIndex();
}<commit_msg>Fixed wrong db usage<commit_after>/*************************************************************************
*    UrBackup - Client/Server backup system
*    Copyright (C) 2011-2016 Martin Raiber
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU Affero General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    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 General Public License for more details.
*
*    You should have received a copy of the GNU Affero General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/

#include "../Interface/Database.h"
#include "../Interface/Server.h"
#include "../Interface/DatabaseCursor.h"
#include "database.h"
#include "server_settings.h"
#include "LMDBFileIndex.h"
#include "../stringtools.h"
#include "../urbackupcommon/os_functions.h"
#include "serverinterface/helper.h"
#include "dao/ServerBackupDao.h"

namespace
{

struct SCallbackData
{
	IDatabaseCursor* cur;
	int64 pos;
	int64 max_pos;
	SStartupStatus* status;
};

db_results create_callback(size_t n_done, size_t n_rows, void *userdata)
{
	SCallbackData *data=(SCallbackData*)userdata;

	data->status->processed_file_entries=n_done;

	int last_pc = static_cast<int>(data->status->pc_done*1000 + 0.5);

	if(data->max_pos>0)
	{
		data->status->pc_done = static_cast<double>(n_rows)/data->max_pos;
	}

	int curr_pc = static_cast<int>(data->status->pc_done*1000 + 0.5);

	if(curr_pc!=last_pc)
	{
		Server->Log("Creating files index: "+convert((double)curr_pc/10)+"% finished", LL_INFO);
	}

	db_results ret;
	db_single_result res;

	if(data->cur->next(res))
	{
		ret.push_back(res);
	}

	return ret;
}

bool create_files_index_common(FileIndex& fileindex, SStartupStatus& status)
{
	IDatabase *db=Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER_FILES);

	db_results cache_res;
	if(db->getEngineName()=="sqlite")
	{
		cache_res=db->Read("PRAGMA cache_size");
		ServerSettings server_settings(db);
		db->Write("PRAGMA cache_size = -"+convert(server_settings.getSettings()->update_stats_cachesize));

		Server->Log("Transitioning urbackup server database to different journaling mode...", LL_INFO);
		db->Write("PRAGMA journal_mode = DELETE");
	}

	status.creating_filesindex=true;
	Server->Log("Creating file entry index. This might take a while...", LL_WARNING);

	Server->Log("Getting number of files...", LL_INFO);

	db_results res = db->Read("SELECT COUNT(*) AS c FROM files");

	int64 n_files = 0;
	if(!res.empty())
	{
		n_files=watoi64(res[0]["c"]);
	}

	db->BeginWriteTransaction();

	Server->Log("Starting creating files index...", LL_INFO);

	IQuery *q_read=db->Prepare("SELECT id, shahash, filesize, clientid, next_entry, prev_entry, pointed_to FROM files ORDER BY shahash ASC, filesize ASC, clientid ASC, created DESC");

	SCallbackData data;
	data.cur=q_read->Cursor();
	data.pos=0;
	data.max_pos=n_files;
	data.status=&status;

	fileindex.create(create_callback, &data);

	if(fileindex.has_error())
	{
		db->Write("ROLLBACK");
		return false;
	}
	else
	{
		db->EndTransaction();
	}

	if(!cache_res.empty())
	{
		db->Write("PRAGMA cache_size = "+cache_res[0]["cache_size"]);
		db->Write("PRAGMA shrink_memory");
		db->Write("PRAGMA journal_mode = WAL");
	}

	status.creating_filesindex=false;

	if(data.cur->has_error())
	{
		return false;
	}

	return true;
}

bool setup_lmdb_file_index(SStartupStatus& status)
{
	LMDBFileIndex fileindex(true);;
	if(fileindex.has_error())
	{
		Server->Log("Error creating file index", LL_ERROR);
		return false;
	}

	return create_files_index_common(fileindex, status);
}

}

void delete_file_index(void)
{
	Server->deleteFile("urbackup/fileindex/backup_server_files_index.lmdb");
	Server->deleteFile("urbackup/fileindex/backup_server_files_index.lmdb-lock");
}

bool create_files_index(SStartupStatus& status)
{
	IDatabase *db=Server->getDatabase(Server->getThreadID(), URBACKUPDB_SERVER);
	ServerSettings settings(db);

	ServerBackupDao backupdao(db);

	bool creating_index = backupdao.getMiscValue("creating_file_entry_index").value=="true";

	if(!FileExists("urbackup/fileindex/backup_server_files_index.lmdb") || creating_index)
	{
		delete_file_index();

		{
			DBScopedSynchronous synchronous_db(db);

			backupdao.delMiscValue("creating_file_entry_index");
			backupdao.addMiscValue("creating_file_entry_index", "true");
		}

		status.upgrading_database=false;
		status.creating_filesindex=true;

		if(!setup_lmdb_file_index(status))
		{
			Server->Log("Setting up file index failed", LL_ERROR);
			return false;
		}
		else
		{
			backupdao.delMiscValue("creating_file_entry_index");
		}
	}

	LMDBFileIndex::initFileIndex();

	return true;

}

FileIndex* create_lmdb_files_index(void)
{
	if(!FileExists("urbackup/fileindex/backup_server_files_index.lmdb"))
	{
		return NULL;
	}

	return new LMDBFileIndex();
}<|endoftext|>