<commit_before>
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkWGL.h"

#include "SkTDArray.h"
#include "SkTSearch.h"

bool SkWGLExtensions::hasExtension(HDC dc, const char* ext) const {
    if (NULL == this->fGetExtensionsString) {
        return false;
    }
    if (!strcmp("WGL_ARB_extensions_string", ext)) {
        return true;
    }
    const char* extensionString = this->getExtensionsString(dc);
    int extLength = strlen(ext);

    while (true) {
        int n = strcspn(extensionString, " ");
        if (n == extLength && 0 == strncmp(ext, extensionString, n)) {
            return true;
        }
        if (0 == extensionString[n]) {
            return false;
        }
        extensionString += n+1;
    }

    return false;
}

const char* SkWGLExtensions::getExtensionsString(HDC hdc) const {
    return fGetExtensionsString(hdc);
}

BOOL SkWGLExtensions::choosePixelFormat(HDC hdc,
                                        const int* piAttribIList,
                                        const FLOAT* pfAttribFList,
                                        UINT nMaxFormats,
                                        int* piFormats,
                                        UINT* nNumFormats) const {
    return fChoosePixelFormat(hdc, piAttribIList, pfAttribFList,
                              nMaxFormats, piFormats, nNumFormats);
}

BOOL SkWGLExtensions::getPixelFormatAttribiv(HDC hdc,
                                             int iPixelFormat,
                                             int iLayerPlane,
                                             UINT nAttributes,
                                             const int *piAttributes,
                                             int *piValues) const {
    return fGetPixelFormatAttribiv(hdc, iPixelFormat, iLayerPlane,
                                   nAttributes, piAttributes, piValues);
}

BOOL SkWGLExtensions::getPixelFormatAttribfv(HDC hdc,
                                             int iPixelFormat,
                                             int iLayerPlane,
                                             UINT nAttributes,
                                             const int *piAttributes,
                                             float *pfValues) const {
    return fGetPixelFormatAttribfv(hdc, iPixelFormat, iLayerPlane,
                                   nAttributes, piAttributes, pfValues);
}
HGLRC SkWGLExtensions::createContextAttribs(HDC hDC,
                                            HGLRC hShareContext,
                                            const int *attribList) const {
    return fCreateContextAttribs(hDC, hShareContext, attribList);
}

namespace {

struct PixelFormat {
    int fFormat;
    int fCoverageSamples;
    int fColorSamples;
    int fChoosePixelFormatRank;
};

int compare_pf(const PixelFormat* a, const PixelFormat* b) {
    if (a->fCoverageSamples < b->fCoverageSamples) {
        return -1;
    } else if (b->fCoverageSamples < a->fCoverageSamples) {
        return 1;
    } else if (a->fColorSamples < b->fColorSamples) {
        return -1;
    } else if (b->fColorSamples < a->fColorSamples) {
        return 1;
    } else if (a->fChoosePixelFormatRank < b->fChoosePixelFormatRank) {
        return -1;
    } else if (b->fChoosePixelFormatRank < a->fChoosePixelFormatRank) {
        return 1;
    }
    return 0;
}
}

int SkWGLExtensions::selectFormat(const int formats[],
                                  int formatCount,
                                  HDC dc,
                                  int desiredSampleCount) {
    PixelFormat desiredFormat = {
        0,
        desiredSampleCount,
        0,
        0,
    };
    SkTDArray<PixelFormat> rankedFormats;
    rankedFormats.setCount(formatCount);
    bool supportsCoverage = this->hasExtension(dc,
                                               "WGL_NV_multisample_coverage");
    for (int i = 0; i < formatCount; ++i) {
        static const int queryAttrs[] = {
            SK_WGL_COVERAGE_SAMPLES,
            SK_WGL_COLOR_SAMPLES,
        };
        int answers[2];
        int queryAttrCnt = supportsCoverage ? 2 : 1;
        this->getPixelFormatAttribiv(dc,
                                     formats[i],
                                     0,
                                     SK_ARRAY_COUNT(queryAttrs),
                                     queryAttrs,
                                     answers);
        rankedFormats[i].fFormat =  formats[i];
        rankedFormats[i].fCoverageSamples = answers[0];
        rankedFormats[i].fColorSamples = answers[supportsCoverage ? 1 : 0];
        rankedFormats[i].fChoosePixelFormatRank = i;
    }
    qsort(rankedFormats.begin(),
            rankedFormats.count(),
            sizeof(PixelFormat),
            SkCastForQSort(compare_pf));
    int idx = SkTSearch<PixelFormat>(rankedFormats.begin(),
                                     rankedFormats.count(),
                                     desiredFormat,
                                     sizeof(PixelFormat),
                                     compare_pf);
    if (idx < 0) {
        idx = ~idx;
    }
    return rankedFormats[idx].fFormat;
}

namespace {

#if defined(UNICODE)
    #define STR_LIT(X) L## #X
#else
    #define STR_LIT(X) #X
#endif

#define DUMMY_CLASS STR_LIT("DummyClass")

HWND create_dummy_window() {
    HMODULE module = GetModuleHandle(NULL);
    HWND dummy;
    RECT windowRect;
    windowRect.left = 0;
    windowRect.right = 8;
    windowRect.top = 0;
    windowRect.bottom = 8;

    WNDCLASS wc;

    wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wc.lpfnWndProc = (WNDPROC) DefWindowProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = module;
    wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = NULL;
    wc.lpszMenuName = NULL;
    wc.lpszClassName = DUMMY_CLASS;

    if(!RegisterClass(&wc)) {
        return 0;
    }

    DWORD style, exStyle;
    exStyle = WS_EX_CLIENTEDGE;
    style = WS_SYSMENU;

    AdjustWindowRectEx(&windowRect, style, false, exStyle);
    if(!(dummy = CreateWindowEx(exStyle,
                                DUMMY_CLASS,
                                STR_LIT("DummyWindow"),
                                WS_CLIPSIBLINGS | WS_CLIPCHILDREN | style,
                                0, 0,
                                windowRect.right-windowRect.left,
                                windowRect.bottom-windowRect.top,
                                NULL, NULL,
                                module,
                                NULL))) {
        UnregisterClass(DUMMY_CLASS, module);
        return NULL;
    }
    ShowWindow(dummy, SW_HIDE);

    return dummy;
}

void destroy_dummy_window(HWND dummy) {
    DestroyWindow(dummy);
    HMODULE module = GetModuleHandle(NULL);
    UnregisterClass(DUMMY_CLASS, module);
}
}

#define GET_PROC(NAME, SUFFIX) f##NAME = \
                     (##NAME##Proc) wglGetProcAddress("wgl" #NAME #SUFFIX)

SkWGLExtensions::SkWGLExtensions()
    : fGetExtensionsString(NULL)
    , fChoosePixelFormat(NULL)
    , fGetPixelFormatAttribfv(NULL)
    , fGetPixelFormatAttribiv(NULL)
    , fCreateContextAttribs(NULL) {
    HDC prevDC = wglGetCurrentDC();
    HGLRC prevGLRC = wglGetCurrentContext();

    PIXELFORMATDESCRIPTOR dummyPFD;

    ZeroMemory(&dummyPFD, sizeof(dummyPFD));
    dummyPFD.nSize = sizeof(dummyPFD);
    dummyPFD.nVersion = 1;
    dummyPFD.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
    dummyPFD.iPixelType = PFD_TYPE_RGBA;
    dummyPFD.cColorBits  = 32;
    dummyPFD.cDepthBits  = 0;
    dummyPFD.cStencilBits = 8;
    dummyPFD.iLayerType = PFD_MAIN_PLANE;
    HWND dummyWND = create_dummy_window();
    if (dummyWND) {
        HDC dummyDC = GetDC(dummyWND);
        int dummyFormat = ChoosePixelFormat(dummyDC, &dummyPFD);
        SetPixelFormat(dummyDC, dummyFormat, &dummyPFD);
        HGLRC dummyGLRC = wglCreateContext(dummyDC);
        SkASSERT(dummyGLRC);
        wglMakeCurrent(dummyDC, dummyGLRC);

        GET_PROC(GetExtensionsString, ARB);
        GET_PROC(ChoosePixelFormat, ARB);
        GET_PROC(GetPixelFormatAttribiv, ARB);
        GET_PROC(GetPixelFormatAttribfv, ARB);
        GET_PROC(CreateContextAttribs, ARB);

        wglMakeCurrent(dummyDC, NULL);
        wglDeleteContext(dummyGLRC);
        destroy_dummy_window(dummyWND);
    }

    wglMakeCurrent(prevDC, prevGLRC);
}
<commit_msg>Fixed unused variable compiler complaint<commit_after>
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkWGL.h"

#include "SkTDArray.h"
#include "SkTSearch.h"

bool SkWGLExtensions::hasExtension(HDC dc, const char* ext) const {
    if (NULL == this->fGetExtensionsString) {
        return false;
    }
    if (!strcmp("WGL_ARB_extensions_string", ext)) {
        return true;
    }
    const char* extensionString = this->getExtensionsString(dc);
    int extLength = strlen(ext);

    while (true) {
        int n = strcspn(extensionString, " ");
        if (n == extLength && 0 == strncmp(ext, extensionString, n)) {
            return true;
        }
        if (0 == extensionString[n]) {
            return false;
        }
        extensionString += n+1;
    }

    return false;
}

const char* SkWGLExtensions::getExtensionsString(HDC hdc) const {
    return fGetExtensionsString(hdc);
}

BOOL SkWGLExtensions::choosePixelFormat(HDC hdc,
                                        const int* piAttribIList,
                                        const FLOAT* pfAttribFList,
                                        UINT nMaxFormats,
                                        int* piFormats,
                                        UINT* nNumFormats) const {
    return fChoosePixelFormat(hdc, piAttribIList, pfAttribFList,
                              nMaxFormats, piFormats, nNumFormats);
}

BOOL SkWGLExtensions::getPixelFormatAttribiv(HDC hdc,
                                             int iPixelFormat,
                                             int iLayerPlane,
                                             UINT nAttributes,
                                             const int *piAttributes,
                                             int *piValues) const {
    return fGetPixelFormatAttribiv(hdc, iPixelFormat, iLayerPlane,
                                   nAttributes, piAttributes, piValues);
}

BOOL SkWGLExtensions::getPixelFormatAttribfv(HDC hdc,
                                             int iPixelFormat,
                                             int iLayerPlane,
                                             UINT nAttributes,
                                             const int *piAttributes,
                                             float *pfValues) const {
    return fGetPixelFormatAttribfv(hdc, iPixelFormat, iLayerPlane,
                                   nAttributes, piAttributes, pfValues);
}
HGLRC SkWGLExtensions::createContextAttribs(HDC hDC,
                                            HGLRC hShareContext,
                                            const int *attribList) const {
    return fCreateContextAttribs(hDC, hShareContext, attribList);
}

namespace {

struct PixelFormat {
    int fFormat;
    int fCoverageSamples;
    int fColorSamples;
    int fChoosePixelFormatRank;
};

int compare_pf(const PixelFormat* a, const PixelFormat* b) {
    if (a->fCoverageSamples < b->fCoverageSamples) {
        return -1;
    } else if (b->fCoverageSamples < a->fCoverageSamples) {
        return 1;
    } else if (a->fColorSamples < b->fColorSamples) {
        return -1;
    } else if (b->fColorSamples < a->fColorSamples) {
        return 1;
    } else if (a->fChoosePixelFormatRank < b->fChoosePixelFormatRank) {
        return -1;
    } else if (b->fChoosePixelFormatRank < a->fChoosePixelFormatRank) {
        return 1;
    }
    return 0;
}
}

int SkWGLExtensions::selectFormat(const int formats[],
                                  int formatCount,
                                  HDC dc,
                                  int desiredSampleCount) {
    PixelFormat desiredFormat = {
        0,
        desiredSampleCount,
        0,
        0,
    };
    SkTDArray<PixelFormat> rankedFormats;
    rankedFormats.setCount(formatCount);
    bool supportsCoverage = this->hasExtension(dc,
                                               "WGL_NV_multisample_coverage");
    for (int i = 0; i < formatCount; ++i) {
        static const int queryAttrs[] = {
            SK_WGL_COVERAGE_SAMPLES,
            // Keep COLOR_SAMPLES at the end so it can be skipped
            SK_WGL_COLOR_SAMPLES,
        };
        int answers[2];
        int queryAttrCnt = supportsCoverage ?
                                    SK_ARRAY_COUNT(queryAttrs) :
                                    SK_ARRAY_COUNT(queryAttrs) - 1;
        this->getPixelFormatAttribiv(dc,
                                     formats[i],
                                     0,
                                     queryAttrCnt,
                                     queryAttrs,
                                     answers);
        rankedFormats[i].fFormat =  formats[i];
        rankedFormats[i].fCoverageSamples = answers[0];
        rankedFormats[i].fColorSamples = answers[supportsCoverage ? 1 : 0];
        rankedFormats[i].fChoosePixelFormatRank = i;
    }
    qsort(rankedFormats.begin(),
            rankedFormats.count(),
            sizeof(PixelFormat),
            SkCastForQSort(compare_pf));
    int idx = SkTSearch<PixelFormat>(rankedFormats.begin(),
                                     rankedFormats.count(),
                                     desiredFormat,
                                     sizeof(PixelFormat),
                                     compare_pf);
    if (idx < 0) {
        idx = ~idx;
    }
    return rankedFormats[idx].fFormat;
}

namespace {

#if defined(UNICODE)
    #define STR_LIT(X) L## #X
#else
    #define STR_LIT(X) #X
#endif

#define DUMMY_CLASS STR_LIT("DummyClass")

HWND create_dummy_window() {
    HMODULE module = GetModuleHandle(NULL);
    HWND dummy;
    RECT windowRect;
    windowRect.left = 0;
    windowRect.right = 8;
    windowRect.top = 0;
    windowRect.bottom = 8;

    WNDCLASS wc;

    wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wc.lpfnWndProc = (WNDPROC) DefWindowProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = module;
    wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = NULL;
    wc.lpszMenuName = NULL;
    wc.lpszClassName = DUMMY_CLASS;

    if(!RegisterClass(&wc)) {
        return 0;
    }

    DWORD style, exStyle;
    exStyle = WS_EX_CLIENTEDGE;
    style = WS_SYSMENU;

    AdjustWindowRectEx(&windowRect, style, false, exStyle);
    if(!(dummy = CreateWindowEx(exStyle,
                                DUMMY_CLASS,
                                STR_LIT("DummyWindow"),
                                WS_CLIPSIBLINGS | WS_CLIPCHILDREN | style,
                                0, 0,
                                windowRect.right-windowRect.left,
                                windowRect.bottom-windowRect.top,
                                NULL, NULL,
                                module,
                                NULL))) {
        UnregisterClass(DUMMY_CLASS, module);
        return NULL;
    }
    ShowWindow(dummy, SW_HIDE);

    return dummy;
}

void destroy_dummy_window(HWND dummy) {
    DestroyWindow(dummy);
    HMODULE module = GetModuleHandle(NULL);
    UnregisterClass(DUMMY_CLASS, module);
}
}

#define GET_PROC(NAME, SUFFIX) f##NAME = \
                     (##NAME##Proc) wglGetProcAddress("wgl" #NAME #SUFFIX)

SkWGLExtensions::SkWGLExtensions()
    : fGetExtensionsString(NULL)
    , fChoosePixelFormat(NULL)
    , fGetPixelFormatAttribfv(NULL)
    , fGetPixelFormatAttribiv(NULL)
    , fCreateContextAttribs(NULL) {
    HDC prevDC = wglGetCurrentDC();
    HGLRC prevGLRC = wglGetCurrentContext();

    PIXELFORMATDESCRIPTOR dummyPFD;

    ZeroMemory(&dummyPFD, sizeof(dummyPFD));
    dummyPFD.nSize = sizeof(dummyPFD);
    dummyPFD.nVersion = 1;
    dummyPFD.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
    dummyPFD.iPixelType = PFD_TYPE_RGBA;
    dummyPFD.cColorBits  = 32;
    dummyPFD.cDepthBits  = 0;
    dummyPFD.cStencilBits = 8;
    dummyPFD.iLayerType = PFD_MAIN_PLANE;
    HWND dummyWND = create_dummy_window();
    if (dummyWND) {
        HDC dummyDC = GetDC(dummyWND);
        int dummyFormat = ChoosePixelFormat(dummyDC, &dummyPFD);
        SetPixelFormat(dummyDC, dummyFormat, &dummyPFD);
        HGLRC dummyGLRC = wglCreateContext(dummyDC);
        SkASSERT(dummyGLRC);
        wglMakeCurrent(dummyDC, dummyGLRC);

        GET_PROC(GetExtensionsString, ARB);
        GET_PROC(ChoosePixelFormat, ARB);
        GET_PROC(GetPixelFormatAttribiv, ARB);
        GET_PROC(GetPixelFormatAttribfv, ARB);
        GET_PROC(CreateContextAttribs, ARB);

        wglMakeCurrent(dummyDC, NULL);
        wglDeleteContext(dummyGLRC);
        destroy_dummy_window(dummyWND);
    }

    wglMakeCurrent(prevDC, prevGLRC);
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2006, Arvid Norberg
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 the author 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.

*/

#include "libtorrent/pch.hpp"

#include <algorithm>
#include <ctime>

#include "libtorrent/kademlia/node_id.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/broadcast_socket.hpp" // for is_local et.al
#include "libtorrent/socket_io.hpp" // for hash_address
#include "libtorrent/random.hpp" // for random

namespace libtorrent { namespace dht
{

// returns the distance between the two nodes
// using the kademlia XOR-metric
node_id distance(node_id const& n1, node_id const& n2)
{
	node_id ret;
	node_id::iterator k = ret.begin();
	for (node_id::const_iterator i = n1.begin(), j = n2.begin()
		, end(n1.end()); i != end; ++i, ++j, ++k)
	{
		*k = *i ^ *j;
	}
	return ret;
}

// returns true if: distance(n1, ref) < distance(n2, ref)
bool compare_ref(node_id const& n1, node_id const& n2, node_id const& ref)
{
	for (node_id::const_iterator i = n1.begin(), j = n2.begin()
		, k = ref.begin(), end(n1.end()); i != end; ++i, ++j, ++k)
	{
		boost::uint8_t lhs = (*i ^ *k);
		boost::uint8_t rhs = (*j ^ *k);
		if (lhs < rhs) return true;
		if (lhs > rhs) return false;
	}
	return false;
}

// returns n in: 2^n <= distance(n1, n2) < 2^(n+1)
// useful for finding out which bucket a node belongs to
int distance_exp(node_id const& n1, node_id const& n2)
{
	int byte = node_id::size - 1;
	for (node_id::const_iterator i = n1.begin(), j = n2.begin()
		, end(n1.end()); i != end; ++i, ++j, --byte)
	{
		TORRENT_ASSERT(byte >= 0);
		boost::uint8_t t = *i ^ *j;
		if (t == 0) continue;
		// we have found the first non-zero byte
		// return the bit-number of the first bit
		// that differs
		int bit = byte * 8;
		for (int b = 7; b >= 0; --b)
			if (t >= (1 << b)) return bit + b;
		return bit;
	}

	return 0;
}

struct static_ { static_() { std::srand((unsigned int)std::time(0)); } } static__;

node_id generate_id_impl(address const& ip_, boost::uint32_t r)
{
	boost::uint8_t* ip = 0;

	const static boost::uint8_t v4mask[] = { 0x03, 0x0f, 0x3f, 0xff };
	const static boost::uint8_t v6mask[] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
	boost::uint8_t const* mask = 0;
	int num_octets = 0;

	address_v4::bytes_type b4;
#if TORRENT_USE_IPV6
	address_v6::bytes_type b6;
	if (ip_.is_v6())
	{
		b6 = ip_.to_v6().to_bytes();
		ip = &b6[0];
		num_octets = 8;
		mask = v6mask;
	}
	else
#endif
	{
		b4 = ip_.to_v4().to_bytes();
		ip = &b4[0];
		num_octets = 4;
		mask = v4mask;
	}

	for (int i = 0; i < num_octets; ++i)
		ip[i] &= mask[i];

	hasher h;
	h.update((char*)ip, num_octets);
	boost::uint8_t rand = r & 0x7;
	h.update((char*)&r, 1);
	node_id id = h.final();
	for (int i = 4; i < 19; ++i) id[i] = random();
	id[19] = r;

	return id;
}

node_id generate_random_id()
{
	char r[20];
	for (int i = 0; i < 20; ++i) r[i] = random();
	return hasher(r, 20).final();
}

// verifies whether a node-id matches the IP it's used from
// returns true if the node-id is OK coming from this source
// and false otherwise.
bool verify_id(node_id const& nid, address const& source_ip)
{
	// no need to verify local IPs, they would be incorrect anyway
	if (is_local(source_ip)) return true;

	node_id h = generate_id_impl(source_ip, nid[19]);
	return memcmp(&nid[0], &h[0], 4) == 0;
}

node_id generate_id(address const& ip)
{
	return generate_id_impl(ip, random());
}

} }  // namespace libtorrent::dht

<commit_msg>and the typo in trunk as well<commit_after>/*

Copyright (c) 2006, Arvid Norberg
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 the author 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.

*/

#include "libtorrent/pch.hpp"

#include <algorithm>
#include <ctime>

#include "libtorrent/kademlia/node_id.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/broadcast_socket.hpp" // for is_local et.al
#include "libtorrent/socket_io.hpp" // for hash_address
#include "libtorrent/random.hpp" // for random

namespace libtorrent { namespace dht
{

// returns the distance between the two nodes
// using the kademlia XOR-metric
node_id distance(node_id const& n1, node_id const& n2)
{
	node_id ret;
	node_id::iterator k = ret.begin();
	for (node_id::const_iterator i = n1.begin(), j = n2.begin()
		, end(n1.end()); i != end; ++i, ++j, ++k)
	{
		*k = *i ^ *j;
	}
	return ret;
}

// returns true if: distance(n1, ref) < distance(n2, ref)
bool compare_ref(node_id const& n1, node_id const& n2, node_id const& ref)
{
	for (node_id::const_iterator i = n1.begin(), j = n2.begin()
		, k = ref.begin(), end(n1.end()); i != end; ++i, ++j, ++k)
	{
		boost::uint8_t lhs = (*i ^ *k);
		boost::uint8_t rhs = (*j ^ *k);
		if (lhs < rhs) return true;
		if (lhs > rhs) return false;
	}
	return false;
}

// returns n in: 2^n <= distance(n1, n2) < 2^(n+1)
// useful for finding out which bucket a node belongs to
int distance_exp(node_id const& n1, node_id const& n2)
{
	int byte = node_id::size - 1;
	for (node_id::const_iterator i = n1.begin(), j = n2.begin()
		, end(n1.end()); i != end; ++i, ++j, --byte)
	{
		TORRENT_ASSERT(byte >= 0);
		boost::uint8_t t = *i ^ *j;
		if (t == 0) continue;
		// we have found the first non-zero byte
		// return the bit-number of the first bit
		// that differs
		int bit = byte * 8;
		for (int b = 7; b >= 0; --b)
			if (t >= (1 << b)) return bit + b;
		return bit;
	}

	return 0;
}

struct static_ { static_() { std::srand((unsigned int)std::time(0)); } } static__;

node_id generate_id_impl(address const& ip_, boost::uint32_t r)
{
	boost::uint8_t* ip = 0;

	const static boost::uint8_t v4mask[] = { 0x03, 0x0f, 0x3f, 0xff };
	const static boost::uint8_t v6mask[] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
	boost::uint8_t const* mask = 0;
	int num_octets = 0;

	address_v4::bytes_type b4;
#if TORRENT_USE_IPV6
	address_v6::bytes_type b6;
	if (ip_.is_v6())
	{
		b6 = ip_.to_v6().to_bytes();
		ip = &b6[0];
		num_octets = 8;
		mask = v6mask;
	}
	else
#endif
	{
		b4 = ip_.to_v4().to_bytes();
		ip = &b4[0];
		num_octets = 4;
		mask = v4mask;
	}

	for (int i = 0; i < num_octets; ++i)
		ip[i] &= mask[i];

	hasher h;
	h.update((char*)ip, num_octets);
	boost::uint8_t rand = r & 0x7;
	h.update((char*)&rand, 1);
	node_id id = h.final();
	for (int i = 4; i < 19; ++i) id[i] = random();
	id[19] = r;

	return id;
}

node_id generate_random_id()
{
	char r[20];
	for (int i = 0; i < 20; ++i) r[i] = random();
	return hasher(r, 20).final();
}

// verifies whether a node-id matches the IP it's used from
// returns true if the node-id is OK coming from this source
// and false otherwise.
bool verify_id(node_id const& nid, address const& source_ip)
{
	// no need to verify local IPs, they would be incorrect anyway
	if (is_local(source_ip)) return true;

	node_id h = generate_id_impl(source_ip, nid[19]);
	return memcmp(&nid[0], &h[0], 4) == 0;
}

node_id generate_id(address const& ip)
{
	return generate_id_impl(ip, random());
}

} }  // namespace libtorrent::dht

<|endoftext|>


<commit_before>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/parameterFitting/CExperimentSet.cpp,v $
   $Revision: 1.19 $
   $Name:  $
   $Author: shoops $
   $Date: 2006/04/20 15:28:42 $
   End CVS Header */

#include <algorithm>
#include <limits>
#include <math.h>

#include "copasi.h"

#include "CExperimentSet.h"
#include "CExperiment.h"

#include "CopasiDataModel/CCopasiDataModel.h"
#include "report/CKeyFactory.h"
#include "utilities/utility.h"

CExperimentSet::CExperimentSet(const std::string & name,
                               const CCopasiContainer * pParent):
    CCopasiParameterGroup(name, pParent, "CExperimentSet"),
    mpExperiments(NULL)
{initializeParameter();}

CExperimentSet::CExperimentSet(const CExperimentSet & src,
                               const CCopasiContainer * pParent):
    CCopasiParameterGroup(src, pParent),
    mpExperiments(NULL)
{initializeParameter();}

CExperimentSet::CExperimentSet(const CCopasiParameterGroup & group,
                               const CCopasiContainer * pParent):
    CCopasiParameterGroup(group, pParent),
    mpExperiments(NULL)
{initializeParameter();}

CExperimentSet::~CExperimentSet() {}

void CExperimentSet::initializeParameter()
{elevateChildren();}

bool CExperimentSet::elevateChildren()
{
  index_iterator it = mValue.pGROUP->begin();
  index_iterator end = mValue.pGROUP->end();

  for (; it != end; ++it)
    if (!elevate<CExperiment, CCopasiParameterGroup>(*it)) return false;

  mpExperiments = static_cast<std::vector<CExperiment * > * >(mValue.pVOID);

  sort();

  return true;
}

bool CExperimentSet::compile(const std::vector< CCopasiContainer * > listOfContainer)
{
  bool success = true;

  // First we need to sort the experiments so that we can make use of continued
  // file reading.
  sort();

  std::set< CCopasiObject * > DependentObjects;

  std::ifstream in;
  std::string CurrentFileName("");
  unsigned C_INT32 CurrentLineNumber = 1;

  std::vector< CExperiment * >::iterator it = mpExperiments->begin();
  std::vector< CExperiment * >::iterator end = mpExperiments->end();

  for (it = mpExperiments->begin(); it != end; ++it)
    {
      if (CurrentFileName != (*it)->getFileName())
        {
          CurrentFileName = (*it)->getFileName();
          CurrentLineNumber = 1;
          if (in.is_open())
            {
              in.close();
              in.clear();
            }

          in.open(CurrentFileName.c_str(), std::ios::binary);
          if (in.fail()) return false; // File can not be opened.
        }

      if (!(*it)->read(in, CurrentLineNumber)) return false;
      if (!(*it)->compile(listOfContainer)) return false;

      const std::map< CCopasiObject *, unsigned C_INT32 > & ExpDependentObjects
      = (*it)->getDependentObjects();
      std::map< CCopasiObject *, unsigned C_INT32 >::const_iterator itObject
      = ExpDependentObjects.begin();
      std::map< CCopasiObject *, unsigned C_INT32 >::const_iterator endObject
      = ExpDependentObjects.end();

      for (; itObject != endObject; ++itObject)
        DependentObjects.insert(itObject->first);
    }

  mDependentObjects.resize(DependentObjects.size());
  CCopasiObject ** ppInsert = mDependentObjects.array();
  std::set< CCopasiObject * >::const_iterator itObject = DependentObjects.begin();
  std::set< CCopasiObject * >::const_iterator endObject = DependentObjects.end();

  for (; itObject != endObject; ++itObject, ++ppInsert)
    *ppInsert = *itObject;

  // Allocation and initialization of statistical information
  mDependentObjectiveValues.resize(mDependentObjects.size());
  mDependentObjectiveValues = std::numeric_limits<C_FLOAT64>::quiet_NaN();

  mDependentRMS.resize(mDependentObjects.size());
  mDependentRMS = std::numeric_limits<C_FLOAT64>::quiet_NaN();

  mDependentErrorMean.resize(mDependentObjects.size());
  mDependentErrorMean = std::numeric_limits<C_FLOAT64>::quiet_NaN();

  mDependentErrorMeanSD.resize(mDependentObjects.size());
  mDependentErrorMeanSD = std::numeric_limits<C_FLOAT64>::quiet_NaN();

  mDependentDataCount.resize(mDependentObjects.size());
  mDependentDataCount = std::numeric_limits<unsigned C_INT32>::quiet_NaN();

  return success;
}

bool CExperimentSet::calculateStatistics()
{
  mDependentObjectiveValues.resize(mDependentObjects.size());
  mDependentObjectiveValues = 0.0;

  mDependentRMS.resize(mDependentObjects.size());
  mDependentRMS = 0.0;

  mDependentErrorMean.resize(mDependentObjects.size());
  mDependentErrorMean = 0.0;

  mDependentErrorMeanSD.resize(mDependentObjects.size());
  mDependentErrorMeanSD = 0.0;

  mDependentDataCount.resize(mDependentObjects.size());
  mDependentDataCount = 0;

  // calclate the per experiment and per dependent value statistics.
  std::vector< CExperiment * >::iterator it = mpExperiments->begin();
  std::vector< CExperiment * >::iterator end = mpExperiments->end();

  unsigned C_INT32 i, Count;
  C_FLOAT64 Tmp;
  for (; it != end; ++it)
    {
      (*it)->calculateStatistics();

      CCopasiObject *const* ppObject = mDependentObjects.array();
      CCopasiObject *const* ppEnd = ppObject + mDependentObjects.size();

      for (i = 0; ppObject != ppEnd; ++ppObject, ++i)
        {
          Count = (*it)->getCount(*ppObject);

          if (Count)
            {
              mDependentObjectiveValues[i] += (*it)->getObjectiveValue(*ppObject);

              Tmp = (*it)->getRMS(*ppObject);
              mDependentRMS[i] += Tmp * Tmp * Count;

              mDependentErrorMean[i] += (*it)->getErrorMean(*ppObject);

              mDependentDataCount[i] += Count;
            }
        }
    }

  unsigned C_INT32 imax = mDependentObjects.size();
  for (i = 0; i != imax; i++)
    {
      Count = mDependentDataCount[i];

      if (Count)
        {
          mDependentRMS[i] = sqrt(mDependentRMS[i] / Count);
          mDependentErrorMean[i] /= Count;
        }
      else
        {
          mDependentRMS[i] = std::numeric_limits<C_FLOAT64>::quiet_NaN();
          mDependentErrorMean[i] = std::numeric_limits<C_FLOAT64>::quiet_NaN();
        }
    }

  it = mpExperiments->begin();

  // We need to loop again to calculate the std. deviation.
  for (; it != end; ++it)
    {
      CCopasiObject *const* ppObject = mDependentObjects.array();
      CCopasiObject *const* ppEnd = ppObject + mDependentObjects.size();

      for (i = 0; ppObject != ppEnd; ++ppObject, ++i)
        {
          Count = (*it)->getCount(*ppObject);

          if (Count)
            mDependentErrorMeanSD[i] +=
              (*it)->getErrorMeanSD(*ppObject, mDependentErrorMean[i]);
        }
    }

  for (i = 0; i != imax; i++)
    {
      Count = mDependentDataCount[i];

      if (Count)
        mDependentErrorMeanSD[i] = sqrt(mDependentErrorMeanSD[i] / Count);
      else
        mDependentErrorMeanSD[i] = std::numeric_limits<C_FLOAT64>::quiet_NaN();
    }

  // :TODO: This is the time to call the output handler to plot the fitted points.
  for (it = mpExperiments->begin(), imax = 0; it != end; ++it)
    imax = std::max(imax, (*it)->getDependentData().numRows());

  for (i = 0; i < imax; i++)
    {
      for (it = mpExperiments->begin(); it != end; ++it)
        (*it)->updateFittedPointValues(i);

      CCopasiDataModel::Global->output(COutputInterface::AFTER);
    }

  return true;
}

const CVector< CCopasiObject * > & CExperimentSet::getDependentObjects() const
{return mDependentObjects;}

const CVector< C_FLOAT64 > & CExperimentSet::getDependentObjectiveValues() const
  {return mDependentObjectiveValues;}

const CVector< C_FLOAT64 > & CExperimentSet::getDependentRMS() const
  {return mDependentRMS;}

const CVector< C_FLOAT64 > & CExperimentSet::getDependentErrorMean() const
  {return mDependentErrorMean;}

const CVector< C_FLOAT64 > & CExperimentSet::getDependentErrorMeanSD() const
  {return mDependentErrorMeanSD;}

CExperiment * CExperimentSet::addExperiment(const CExperiment & experiment)
{
  // We need to make sure that the experiment name is unique.
  std::string name = experiment.getObjectName();

  int i = 0;
  while (getParameter(name))
    {
      i++;
      name = StringPrint("%s_%d", experiment.getObjectName().c_str(), i);
    }

  CExperiment * pExperiment = new CExperiment(experiment);
  pExperiment->setObjectName(name);
  addParameter(pExperiment);

  sort();

  return pExperiment;
}

CExperiment * CExperimentSet::getExperiment(const unsigned C_INT32 & index)
{return (*mpExperiments)[index];}

const CExperiment * CExperimentSet::getExperiment(const unsigned C_INT32 & index) const
  {return (*mpExperiments)[index];}

CExperiment * CExperimentSet::getExperiment(const std::string & name)
{return static_cast<CExperiment *>(getGroup(name));}

const CExperiment * CExperimentSet::getExperiment(const std::string & name) const
  {return static_cast<const CExperiment *>(getGroup(name));}

const CCopasiTask::Type & CExperimentSet::getExperimentType(const unsigned C_INT32 & index) const
  {return getExperiment(index)->getExperimentType();}

const CMatrix< C_FLOAT64 > & CExperimentSet::getIndependentData(const unsigned C_INT32 & index) const
  {return getExperiment(index)->getIndependentData();}

const CMatrix< C_FLOAT64 > & CExperimentSet::getDependentData(const unsigned C_INT32 & index) const
  {return getExperiment(index)->getDependentData();}

unsigned C_INT32 CExperimentSet::keyToIndex(const std::string & key) const
  {
    const CExperiment * pExp = dynamic_cast<const CExperiment *>(GlobalKeys.get(key));

    if (!pExp) return C_INVALID_INDEX;

    unsigned C_INT32 i, imax = size();

    for (i = 0; i < imax; i++)
      if (pExp == getExperiment(i)) return i;

    return C_INVALID_INDEX;
  }

void CExperimentSet::sort()
{
  std::vector< CExperiment * >::iterator it = mpExperiments->begin();
  std::vector< CExperiment * >::iterator end = mpExperiments->end();

  std::sort(it, end, &CExperiment::compare);

  return;
}

std::vector< std::string > CExperimentSet::getFileNames() const
  {
    std::vector< std::string > List;
    std::string currentFile = "";

    std::vector< CExperiment * >::iterator it = mpExperiments->begin();
    std::vector< CExperiment * >::iterator end = mpExperiments->end();

    for (; it != end; ++it)
      if (currentFile != (*it)->getFileName())
        {
          currentFile = (*it)->getFileName();
          List.push_back(currentFile);
        }

    return List;
  }

unsigned C_INT32 CExperimentSet::getDataPointCount() const
  {
    unsigned C_INT32 Count = 0;
    std::vector< CExperiment * >::iterator it = mpExperiments->begin();
    std::vector< CExperiment * >::iterator end = mpExperiments->end();

    for (; it != end; ++it)
      Count += (*it)->getDependentData().numRows() * (*it)->getDependentData().numCols();

    return Count;
  }
<commit_msg>Removed :TODO: comment :)<commit_after>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/parameterFitting/CExperimentSet.cpp,v $
   $Revision: 1.20 $
   $Name:  $
   $Author: shoops $
   $Date: 2006/04/21 19:15:56 $
   End CVS Header */

#include <algorithm>
#include <limits>
#include <math.h>

#include "copasi.h"

#include "CExperimentSet.h"
#include "CExperiment.h"

#include "CopasiDataModel/CCopasiDataModel.h"
#include "report/CKeyFactory.h"
#include "utilities/utility.h"

CExperimentSet::CExperimentSet(const std::string & name,
                               const CCopasiContainer * pParent):
    CCopasiParameterGroup(name, pParent, "CExperimentSet"),
    mpExperiments(NULL)
{initializeParameter();}

CExperimentSet::CExperimentSet(const CExperimentSet & src,
                               const CCopasiContainer * pParent):
    CCopasiParameterGroup(src, pParent),
    mpExperiments(NULL)
{initializeParameter();}

CExperimentSet::CExperimentSet(const CCopasiParameterGroup & group,
                               const CCopasiContainer * pParent):
    CCopasiParameterGroup(group, pParent),
    mpExperiments(NULL)
{initializeParameter();}

CExperimentSet::~CExperimentSet() {}

void CExperimentSet::initializeParameter()
{elevateChildren();}

bool CExperimentSet::elevateChildren()
{
  index_iterator it = mValue.pGROUP->begin();
  index_iterator end = mValue.pGROUP->end();

  for (; it != end; ++it)
    if (!elevate<CExperiment, CCopasiParameterGroup>(*it)) return false;

  mpExperiments = static_cast<std::vector<CExperiment * > * >(mValue.pVOID);

  sort();

  return true;
}

bool CExperimentSet::compile(const std::vector< CCopasiContainer * > listOfContainer)
{
  bool success = true;

  // First we need to sort the experiments so that we can make use of continued
  // file reading.
  sort();

  std::set< CCopasiObject * > DependentObjects;

  std::ifstream in;
  std::string CurrentFileName("");
  unsigned C_INT32 CurrentLineNumber = 1;

  std::vector< CExperiment * >::iterator it = mpExperiments->begin();
  std::vector< CExperiment * >::iterator end = mpExperiments->end();

  for (it = mpExperiments->begin(); it != end; ++it)
    {
      if (CurrentFileName != (*it)->getFileName())
        {
          CurrentFileName = (*it)->getFileName();
          CurrentLineNumber = 1;
          if (in.is_open())
            {
              in.close();
              in.clear();
            }

          in.open(CurrentFileName.c_str(), std::ios::binary);
          if (in.fail()) return false; // File can not be opened.
        }

      if (!(*it)->read(in, CurrentLineNumber)) return false;
      if (!(*it)->compile(listOfContainer)) return false;

      const std::map< CCopasiObject *, unsigned C_INT32 > & ExpDependentObjects
      = (*it)->getDependentObjects();
      std::map< CCopasiObject *, unsigned C_INT32 >::const_iterator itObject
      = ExpDependentObjects.begin();
      std::map< CCopasiObject *, unsigned C_INT32 >::const_iterator endObject
      = ExpDependentObjects.end();

      for (; itObject != endObject; ++itObject)
        DependentObjects.insert(itObject->first);
    }

  mDependentObjects.resize(DependentObjects.size());
  CCopasiObject ** ppInsert = mDependentObjects.array();
  std::set< CCopasiObject * >::const_iterator itObject = DependentObjects.begin();
  std::set< CCopasiObject * >::const_iterator endObject = DependentObjects.end();

  for (; itObject != endObject; ++itObject, ++ppInsert)
    *ppInsert = *itObject;

  // Allocation and initialization of statistical information
  mDependentObjectiveValues.resize(mDependentObjects.size());
  mDependentObjectiveValues = std::numeric_limits<C_FLOAT64>::quiet_NaN();

  mDependentRMS.resize(mDependentObjects.size());
  mDependentRMS = std::numeric_limits<C_FLOAT64>::quiet_NaN();

  mDependentErrorMean.resize(mDependentObjects.size());
  mDependentErrorMean = std::numeric_limits<C_FLOAT64>::quiet_NaN();

  mDependentErrorMeanSD.resize(mDependentObjects.size());
  mDependentErrorMeanSD = std::numeric_limits<C_FLOAT64>::quiet_NaN();

  mDependentDataCount.resize(mDependentObjects.size());
  mDependentDataCount = std::numeric_limits<unsigned C_INT32>::quiet_NaN();

  return success;
}

bool CExperimentSet::calculateStatistics()
{
  mDependentObjectiveValues.resize(mDependentObjects.size());
  mDependentObjectiveValues = 0.0;

  mDependentRMS.resize(mDependentObjects.size());
  mDependentRMS = 0.0;

  mDependentErrorMean.resize(mDependentObjects.size());
  mDependentErrorMean = 0.0;

  mDependentErrorMeanSD.resize(mDependentObjects.size());
  mDependentErrorMeanSD = 0.0;

  mDependentDataCount.resize(mDependentObjects.size());
  mDependentDataCount = 0;

  // calclate the per experiment and per dependent value statistics.
  std::vector< CExperiment * >::iterator it = mpExperiments->begin();
  std::vector< CExperiment * >::iterator end = mpExperiments->end();

  unsigned C_INT32 i, Count;
  C_FLOAT64 Tmp;
  for (; it != end; ++it)
    {
      (*it)->calculateStatistics();

      CCopasiObject *const* ppObject = mDependentObjects.array();
      CCopasiObject *const* ppEnd = ppObject + mDependentObjects.size();

      for (i = 0; ppObject != ppEnd; ++ppObject, ++i)
        {
          Count = (*it)->getCount(*ppObject);

          if (Count)
            {
              mDependentObjectiveValues[i] += (*it)->getObjectiveValue(*ppObject);

              Tmp = (*it)->getRMS(*ppObject);
              mDependentRMS[i] += Tmp * Tmp * Count;

              mDependentErrorMean[i] += (*it)->getErrorMean(*ppObject);

              mDependentDataCount[i] += Count;
            }
        }
    }

  unsigned C_INT32 imax = mDependentObjects.size();
  for (i = 0; i != imax; i++)
    {
      Count = mDependentDataCount[i];

      if (Count)
        {
          mDependentRMS[i] = sqrt(mDependentRMS[i] / Count);
          mDependentErrorMean[i] /= Count;
        }
      else
        {
          mDependentRMS[i] = std::numeric_limits<C_FLOAT64>::quiet_NaN();
          mDependentErrorMean[i] = std::numeric_limits<C_FLOAT64>::quiet_NaN();
        }
    }

  it = mpExperiments->begin();

  // We need to loop again to calculate the std. deviation.
  for (; it != end; ++it)
    {
      CCopasiObject *const* ppObject = mDependentObjects.array();
      CCopasiObject *const* ppEnd = ppObject + mDependentObjects.size();

      for (i = 0; ppObject != ppEnd; ++ppObject, ++i)
        {
          Count = (*it)->getCount(*ppObject);

          if (Count)
            mDependentErrorMeanSD[i] +=
              (*it)->getErrorMeanSD(*ppObject, mDependentErrorMean[i]);
        }
    }

  for (i = 0; i != imax; i++)
    {
      Count = mDependentDataCount[i];

      if (Count)
        mDependentErrorMeanSD[i] = sqrt(mDependentErrorMeanSD[i] / Count);
      else
        mDependentErrorMeanSD[i] = std::numeric_limits<C_FLOAT64>::quiet_NaN();
    }

  // This is the time to call the output handler to plot the fitted points.
  for (it = mpExperiments->begin(), imax = 0; it != end; ++it)
    imax = std::max(imax, (*it)->getDependentData().numRows());

  for (i = 0; i < imax; i++)
    {
      for (it = mpExperiments->begin(); it != end; ++it)
        (*it)->updateFittedPointValues(i);

      CCopasiDataModel::Global->output(COutputInterface::AFTER);
    }

  return true;
}

const CVector< CCopasiObject * > & CExperimentSet::getDependentObjects() const
{return mDependentObjects;}

const CVector< C_FLOAT64 > & CExperimentSet::getDependentObjectiveValues() const
  {return mDependentObjectiveValues;}

const CVector< C_FLOAT64 > & CExperimentSet::getDependentRMS() const
  {return mDependentRMS;}

const CVector< C_FLOAT64 > & CExperimentSet::getDependentErrorMean() const
  {return mDependentErrorMean;}

const CVector< C_FLOAT64 > & CExperimentSet::getDependentErrorMeanSD() const
  {return mDependentErrorMeanSD;}

CExperiment * CExperimentSet::addExperiment(const CExperiment & experiment)
{
  // We need to make sure that the experiment name is unique.
  std::string name = experiment.getObjectName();

  int i = 0;
  while (getParameter(name))
    {
      i++;
      name = StringPrint("%s_%d", experiment.getObjectName().c_str(), i);
    }

  CExperiment * pExperiment = new CExperiment(experiment);
  pExperiment->setObjectName(name);
  addParameter(pExperiment);

  sort();

  return pExperiment;
}

CExperiment * CExperimentSet::getExperiment(const unsigned C_INT32 & index)
{return (*mpExperiments)[index];}

const CExperiment * CExperimentSet::getExperiment(const unsigned C_INT32 & index) const
  {return (*mpExperiments)[index];}

CExperiment * CExperimentSet::getExperiment(const std::string & name)
{return static_cast<CExperiment *>(getGroup(name));}

const CExperiment * CExperimentSet::getExperiment(const std::string & name) const
  {return static_cast<const CExperiment *>(getGroup(name));}

const CCopasiTask::Type & CExperimentSet::getExperimentType(const unsigned C_INT32 & index) const
  {return getExperiment(index)->getExperimentType();}

const CMatrix< C_FLOAT64 > & CExperimentSet::getIndependentData(const unsigned C_INT32 & index) const
  {return getExperiment(index)->getIndependentData();}

const CMatrix< C_FLOAT64 > & CExperimentSet::getDependentData(const unsigned C_INT32 & index) const
  {return getExperiment(index)->getDependentData();}

unsigned C_INT32 CExperimentSet::keyToIndex(const std::string & key) const
  {
    const CExperiment * pExp = dynamic_cast<const CExperiment *>(GlobalKeys.get(key));

    if (!pExp) return C_INVALID_INDEX;

    unsigned C_INT32 i, imax = size();

    for (i = 0; i < imax; i++)
      if (pExp == getExperiment(i)) return i;

    return C_INVALID_INDEX;
  }

void CExperimentSet::sort()
{
  std::vector< CExperiment * >::iterator it = mpExperiments->begin();
  std::vector< CExperiment * >::iterator end = mpExperiments->end();

  std::sort(it, end, &CExperiment::compare);

  return;
}

std::vector< std::string > CExperimentSet::getFileNames() const
  {
    std::vector< std::string > List;
    std::string currentFile = "";

    std::vector< CExperiment * >::iterator it = mpExperiments->begin();
    std::vector< CExperiment * >::iterator end = mpExperiments->end();

    for (; it != end; ++it)
      if (currentFile != (*it)->getFileName())
        {
          currentFile = (*it)->getFileName();
          List.push_back(currentFile);
        }

    return List;
  }

unsigned C_INT32 CExperimentSet::getDataPointCount() const
  {
    unsigned C_INT32 Count = 0;
    std::vector< CExperiment * >::iterator it = mpExperiments->begin();
    std::vector< CExperiment * >::iterator end = mpExperiments->end();

    for (; it != end; ++it)
      Count += (*it)->getDependentData().numRows() * (*it)->getDependentData().numCols();

    return Count;
  }
<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.html

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 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 Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.

You may alternatively use this source under the terms of a specific version of
the OGRE Unrestricted License provided you have obtained such a license from
Torus Knot Software Ltd.
-----------------------------------------------------------------------------
*/
#include "OgreStableHeaders.h"

#include "OgreMovableObject.h"
#include "OgreSceneNode.h"
#include "OgreTagPoint.h"
#include "OgreLight.h"
#include "OgreEntity.h"
#include "OgreRoot.h"
#include "OgreSceneManager.h"
#include "OgreCamera.h"
#include "OgreLodListener.h"

namespace Ogre {
	//-----------------------------------------------------------------------
	//-----------------------------------------------------------------------
	uint32 MovableObject::msDefaultQueryFlags = 0xFFFFFFFF;
	uint32 MovableObject::msDefaultVisibilityFlags = 0xFFFFFFFF;
    //-----------------------------------------------------------------------
    MovableObject::MovableObject()
        : mCreator(0)
        , mManager(0)
        , mParentNode(0)
        , mParentIsTagPoint(false)
        , mVisible(true)
		, mDebugDisplay(false)
        , mUpperDistance(0)
        , mSquaredUpperDistance(0)
        , mBeyondFarDistance(false)
        , mRenderQueueID(RENDER_QUEUE_MAIN)
        , mRenderQueueIDSet(false)
        , mQueryFlags(msDefaultQueryFlags)
        , mVisibilityFlags(msDefaultVisibilityFlags)
        , mCastShadows(true)
        , mRenderingDisabled(false)
        , mListener(0)
        , mLightListUpdated(0)
		, mLightMask(0xFFFFFFFF)
    {
    }
    //-----------------------------------------------------------------------
    MovableObject::MovableObject(const String& name)
        : mName(name)
        , mCreator(0)
        , mManager(0)
        , mParentNode(0)
        , mParentIsTagPoint(false)
        , mVisible(true)
		, mDebugDisplay(false)
        , mUpperDistance(0)
        , mSquaredUpperDistance(0)
        , mBeyondFarDistance(false)
        , mRenderQueueID(RENDER_QUEUE_MAIN)
        , mRenderQueueIDSet(false)
        , mQueryFlags(msDefaultQueryFlags)
        , mVisibilityFlags(msDefaultVisibilityFlags)
        , mCastShadows(true)
        , mRenderingDisabled(false)
        , mListener(0)
        , mLightListUpdated(0)
		, mLightMask(0xFFFFFFFF)
    {
    }
    //-----------------------------------------------------------------------
    MovableObject::~MovableObject()
    {
        // Call listener (note, only called if there's something to do)
        if (mListener)
        {
            mListener->objectDestroyed(this);
        }

        if (mParentNode)
        {
            // detach from parent
            if (mParentIsTagPoint)
            {
                // May be we are a lod entity which not in the parent entity child object list,
                // call this method could safely ignore this case.
                static_cast<TagPoint*>(mParentNode)->getParentEntity()->detachObjectFromBone(this);
            }
            else
            {
                // May be we are a lod entity which not in the parent node child object list,
                // call this method could safely ignore this case.
                static_cast<SceneNode*>(mParentNode)->detachObject(this);
            }
        }
    }
    //-----------------------------------------------------------------------
    void MovableObject::_notifyAttached(Node* parent, bool isTagPoint)
    {
        assert(!mParentNode || !parent);

        bool different = (parent != mParentNode);

        mParentNode = parent;
        mParentIsTagPoint = isTagPoint;

        // Mark light list being dirty, simply decrease
        // counter by one for minimise overhead
        --mLightListUpdated;

        // Call listener (note, only called if there's something to do)
        if (mListener && different)
        {
            if (mParentNode)
                mListener->objectAttached(this);
            else
                mListener->objectDetached(this);
        }
    }
    //-----------------------------------------------------------------------
    Node* MovableObject::getParentNode(void) const
    {
        return mParentNode;
    }
    //-----------------------------------------------------------------------
    SceneNode* MovableObject::getParentSceneNode(void) const
    {
        if (mParentIsTagPoint)
        {
            TagPoint* tp = static_cast<TagPoint*>(mParentNode);
            return tp->getParentEntity()->getParentSceneNode();
        }
        else
        {
            return static_cast<SceneNode*>(mParentNode);
        }
    }
    //-----------------------------------------------------------------------
    bool MovableObject::isAttached(void) const
    {
        return (mParentNode != 0);

    }
	//---------------------------------------------------------------------
	void MovableObject::detachFromParent(void)
	{
		if (isAttached())
		{
			if (mParentIsTagPoint)
			{
				TagPoint* tp = static_cast<TagPoint*>(mParentNode);
				tp->getParentEntity()->detachObjectFromBone(this);
			}
			else
			{
				SceneNode* sn = static_cast<SceneNode*>(mParentNode);
				sn->detachObject(this);
			}
		}
	}
    //-----------------------------------------------------------------------
	bool MovableObject::isInScene(void) const
	{
		if (mParentNode != 0)
		{
			if (mParentIsTagPoint)
			{
				TagPoint* tp = static_cast<TagPoint*>(mParentNode);
				return tp->getParentEntity()->isInScene();
			}
			else
			{
				SceneNode* sn = static_cast<SceneNode*>(mParentNode);
				return sn->isInSceneGraph();
			}
		}
		else
		{
			return false;
		}
	}
    //-----------------------------------------------------------------------
    void MovableObject::_notifyMoved(void)
    {
        // Mark light list being dirty, simply decrease
        // counter by one for minimise overhead
        --mLightListUpdated;

        // Notify listener if exists
        if (mListener)
        {
            mListener->objectMoved(this);
        }
    }
    //-----------------------------------------------------------------------
    void MovableObject::setVisible(bool visible)
    {
        mVisible = visible;
    }
    //-----------------------------------------------------------------------
    bool MovableObject::getVisible(void) const
    {
        return mVisible;
    }
    //-----------------------------------------------------------------------
    bool MovableObject::isVisible(void) const
    {
        if (!mVisible || mBeyondFarDistance || mRenderingDisabled)
            return false;

        SceneManager* sm = Root::getSingleton()._getCurrentSceneManager();
        if (sm && !(mVisibilityFlags & sm->_getCombinedVisibilityMask()))
            return false;

        return true;
    }
	//-----------------------------------------------------------------------
	void MovableObject::_notifyCurrentCamera(Camera* cam)
	{
		if (mParentNode)
		{
			if (cam->getUseRenderingDistance() && mUpperDistance > 0)
			{
				Real rad = getBoundingRadius();
				Real squaredDepth = mParentNode->getSquaredViewDepth(cam->getLodCamera());
				// Max distance to still render
				Real maxDist = mUpperDistance + rad;
				if (squaredDepth > Math::Sqr(maxDist))
				{
					mBeyondFarDistance = true;
				}
				else
				{
					mBeyondFarDistance = false;
				}
			}
			else
			{
				mBeyondFarDistance = false;
			}

            // Construct event object
            MovableObjectLodChangedEvent evt;
            evt.movableObject = this;
            evt.camera = cam;

            // Notify lod event listeners
            cam->getSceneManager()->_notifyMovableObjectLodChanged(evt);

		}

        mRenderingDisabled = mListener && !mListener->objectRendering(this, cam);
	}
    //-----------------------------------------------------------------------
    void MovableObject::setRenderQueueGroup(uint8 queueID)
    {
		assert(queueID <= RENDER_QUEUE_MAX && "Render queue out of range!");
        mRenderQueueID = queueID;
        mRenderQueueIDSet = true;
    }
    //-----------------------------------------------------------------------
    uint8 MovableObject::getRenderQueueGroup(void) const
    {
        return mRenderQueueID;
    }
    //-----------------------------------------------------------------------
	const Matrix4& MovableObject::_getParentNodeFullTransform(void) const
	{

		if(mParentNode)
		{
			// object attached to a sceneNode
			return mParentNode->_getFullTransform();
		}
        // fallback
        return Matrix4::IDENTITY;
	}
    //-----------------------------------------------------------------------
    const AxisAlignedBox& MovableObject::getWorldBoundingBox(bool derive) const
    {
        if (derive)
        {
            mWorldAABB = this->getBoundingBox();
            mWorldAABB.transformAffine(_getParentNodeFullTransform());
        }

        return mWorldAABB;

    }
    //-----------------------------------------------------------------------
	const Sphere& MovableObject::getWorldBoundingSphere(bool derive) const
	{
		if (derive)
		{
			mWorldBoundingSphere.setRadius(getBoundingRadius());
			mWorldBoundingSphere.setCenter(mParentNode->_getDerivedPosition());
		}
		return mWorldBoundingSphere;
	}
    //-----------------------------------------------------------------------
    const LightList& MovableObject::queryLights(void) const
    {
        // Try listener first
        if (mListener)
        {
            const LightList* lightList =
                mListener->objectQueryLights(this);
            if (lightList)
            {
                return *lightList;
            }
        }

        // Query from parent entity if exists
        if (mParentIsTagPoint)
        {
            TagPoint* tp = static_cast<TagPoint*>(mParentNode);
            return tp->getParentEntity()->queryLights();
        }

        if (mParentNode)
        {
            SceneNode* sn = static_cast<SceneNode*>(mParentNode);

            // Make sure we only update this only if need.
            ulong frame = sn->getCreator()->_getLightsDirtyCounter();
            if (mLightListUpdated != frame)
            {
                mLightListUpdated = frame;

                sn->findLights(mLightList, this->getBoundingRadius(), this->getLightMask());
            }
        }
        else
        {
            mLightList.clear();
        }

        return mLightList;
    }
    //-----------------------------------------------------------------------
    ShadowCaster::ShadowRenderableListIterator MovableObject::getShadowVolumeRenderableIterator(
        ShadowTechnique shadowTechnique, const Light* light,
        HardwareIndexBufferSharedPtr* indexBuffer,
        bool extrudeVertices, Real extrusionDist, unsigned long flags )
    {
        static ShadowRenderableList dummyList;
        return ShadowRenderableListIterator(dummyList.begin(), dummyList.end());
    }
    //-----------------------------------------------------------------------
    const AxisAlignedBox& MovableObject::getLightCapBounds(void) const
    {
        // Same as original bounds
        return getWorldBoundingBox();
    }
    //-----------------------------------------------------------------------
    const AxisAlignedBox& MovableObject::getDarkCapBounds(const Light& light, Real extrusionDist) const
    {
        // Extrude own light cap bounds
        mWorldDarkCapBounds = getLightCapBounds();
        this->extrudeBounds(mWorldDarkCapBounds, light.getAs4DVector(),
            extrusionDist);
        return mWorldDarkCapBounds;

    }
    //-----------------------------------------------------------------------
    Real MovableObject::getPointExtrusionDistance(const Light* l) const
    {
        if (mParentNode)
        {
            return getExtrusionDistance(mParentNode->_getDerivedPosition(), l);
        }
        else
        {
            return 0;
        }
    }
	//-----------------------------------------------------------------------
	uint32 MovableObject::getTypeFlags(void) const
	{
		if (mCreator)
		{
			return mCreator->getTypeFlags();
		}
		else
		{
			return 0xFFFFFFFF;
		}
	}
	//---------------------------------------------------------------------
	void MovableObject::setLightMask(uint32 lightMask)
	{
		this->mLightMask = lightMask;
		//make sure to request a new light list from the scene manager if mask changed
		mLightListUpdated = 0;
	}
	//---------------------------------------------------------------------
	class MORecvShadVisitor : public Renderable::Visitor
	{
	public:
		bool anyReceiveShadows;
		MORecvShadVisitor() : anyReceiveShadows(false)
		{

		}
		void visit(Renderable* rend, ushort lodIndex, bool isDebug,
			Any* pAny = 0)
		{
			anyReceiveShadows = anyReceiveShadows ||
				rend->getTechnique()->getParent()->getReceiveShadows();
		}
	};
	//---------------------------------------------------------------------
	bool MovableObject::getReceivesShadows()
	{
		MORecvShadVisitor visitor;
		visitRenderables(&visitor);
		return visitor.anyReceiveShadows;

	}
	//-----------------------------------------------------------------------
	//-----------------------------------------------------------------------
	MovableObject* MovableObjectFactory::createInstance(
		const String& name, SceneManager* manager,
		const NameValuePairList* params)
	{
		MovableObject* m = createInstanceImpl(name, params);
		m->_notifyCreator(this);
		m->_notifyManager(manager);
		return m;
	}

}

<commit_msg>Tolerate Renderable::getTechnique returning null in MORecvShadVisitor::visit<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.html

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 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 Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.

You may alternatively use this source under the terms of a specific version of
the OGRE Unrestricted License provided you have obtained such a license from
Torus Knot Software Ltd.
-----------------------------------------------------------------------------
*/
#include "OgreStableHeaders.h"

#include "OgreMovableObject.h"
#include "OgreSceneNode.h"
#include "OgreTagPoint.h"
#include "OgreLight.h"
#include "OgreEntity.h"
#include "OgreRoot.h"
#include "OgreSceneManager.h"
#include "OgreCamera.h"
#include "OgreLodListener.h"

namespace Ogre {
	//-----------------------------------------------------------------------
	//-----------------------------------------------------------------------
	uint32 MovableObject::msDefaultQueryFlags = 0xFFFFFFFF;
	uint32 MovableObject::msDefaultVisibilityFlags = 0xFFFFFFFF;
    //-----------------------------------------------------------------------
    MovableObject::MovableObject()
        : mCreator(0)
        , mManager(0)
        , mParentNode(0)
        , mParentIsTagPoint(false)
        , mVisible(true)
		, mDebugDisplay(false)
        , mUpperDistance(0)
        , mSquaredUpperDistance(0)
        , mBeyondFarDistance(false)
        , mRenderQueueID(RENDER_QUEUE_MAIN)
        , mRenderQueueIDSet(false)
        , mQueryFlags(msDefaultQueryFlags)
        , mVisibilityFlags(msDefaultVisibilityFlags)
        , mCastShadows(true)
        , mRenderingDisabled(false)
        , mListener(0)
        , mLightListUpdated(0)
		, mLightMask(0xFFFFFFFF)
    {
    }
    //-----------------------------------------------------------------------
    MovableObject::MovableObject(const String& name)
        : mName(name)
        , mCreator(0)
        , mManager(0)
        , mParentNode(0)
        , mParentIsTagPoint(false)
        , mVisible(true)
		, mDebugDisplay(false)
        , mUpperDistance(0)
        , mSquaredUpperDistance(0)
        , mBeyondFarDistance(false)
        , mRenderQueueID(RENDER_QUEUE_MAIN)
        , mRenderQueueIDSet(false)
        , mQueryFlags(msDefaultQueryFlags)
        , mVisibilityFlags(msDefaultVisibilityFlags)
        , mCastShadows(true)
        , mRenderingDisabled(false)
        , mListener(0)
        , mLightListUpdated(0)
		, mLightMask(0xFFFFFFFF)
    {
    }
    //-----------------------------------------------------------------------
    MovableObject::~MovableObject()
    {
        // Call listener (note, only called if there's something to do)
        if (mListener)
        {
            mListener->objectDestroyed(this);
        }

        if (mParentNode)
        {
            // detach from parent
            if (mParentIsTagPoint)
            {
                // May be we are a lod entity which not in the parent entity child object list,
                // call this method could safely ignore this case.
                static_cast<TagPoint*>(mParentNode)->getParentEntity()->detachObjectFromBone(this);
            }
            else
            {
                // May be we are a lod entity which not in the parent node child object list,
                // call this method could safely ignore this case.
                static_cast<SceneNode*>(mParentNode)->detachObject(this);
            }
        }
    }
    //-----------------------------------------------------------------------
    void MovableObject::_notifyAttached(Node* parent, bool isTagPoint)
    {
        assert(!mParentNode || !parent);

        bool different = (parent != mParentNode);

        mParentNode = parent;
        mParentIsTagPoint = isTagPoint;

        // Mark light list being dirty, simply decrease
        // counter by one for minimise overhead
        --mLightListUpdated;

        // Call listener (note, only called if there's something to do)
        if (mListener && different)
        {
            if (mParentNode)
                mListener->objectAttached(this);
            else
                mListener->objectDetached(this);
        }
    }
    //-----------------------------------------------------------------------
    Node* MovableObject::getParentNode(void) const
    {
        return mParentNode;
    }
    //-----------------------------------------------------------------------
    SceneNode* MovableObject::getParentSceneNode(void) const
    {
        if (mParentIsTagPoint)
        {
            TagPoint* tp = static_cast<TagPoint*>(mParentNode);
            return tp->getParentEntity()->getParentSceneNode();
        }
        else
        {
            return static_cast<SceneNode*>(mParentNode);
        }
    }
    //-----------------------------------------------------------------------
    bool MovableObject::isAttached(void) const
    {
        return (mParentNode != 0);

    }
	//---------------------------------------------------------------------
	void MovableObject::detachFromParent(void)
	{
		if (isAttached())
		{
			if (mParentIsTagPoint)
			{
				TagPoint* tp = static_cast<TagPoint*>(mParentNode);
				tp->getParentEntity()->detachObjectFromBone(this);
			}
			else
			{
				SceneNode* sn = static_cast<SceneNode*>(mParentNode);
				sn->detachObject(this);
			}
		}
	}
    //-----------------------------------------------------------------------
	bool MovableObject::isInScene(void) const
	{
		if (mParentNode != 0)
		{
			if (mParentIsTagPoint)
			{
				TagPoint* tp = static_cast<TagPoint*>(mParentNode);
				return tp->getParentEntity()->isInScene();
			}
			else
			{
				SceneNode* sn = static_cast<SceneNode*>(mParentNode);
				return sn->isInSceneGraph();
			}
		}
		else
		{
			return false;
		}
	}
    //-----------------------------------------------------------------------
    void MovableObject::_notifyMoved(void)
    {
        // Mark light list being dirty, simply decrease
        // counter by one for minimise overhead
        --mLightListUpdated;

        // Notify listener if exists
        if (mListener)
        {
            mListener->objectMoved(this);
        }
    }
    //-----------------------------------------------------------------------
    void MovableObject::setVisible(bool visible)
    {
        mVisible = visible;
    }
    //-----------------------------------------------------------------------
    bool MovableObject::getVisible(void) const
    {
        return mVisible;
    }
    //-----------------------------------------------------------------------
    bool MovableObject::isVisible(void) const
    {
        if (!mVisible || mBeyondFarDistance || mRenderingDisabled)
            return false;

        SceneManager* sm = Root::getSingleton()._getCurrentSceneManager();
        if (sm && !(mVisibilityFlags & sm->_getCombinedVisibilityMask()))
            return false;

        return true;
    }
	//-----------------------------------------------------------------------
	void MovableObject::_notifyCurrentCamera(Camera* cam)
	{
		if (mParentNode)
		{
			if (cam->getUseRenderingDistance() && mUpperDistance > 0)
			{
				Real rad = getBoundingRadius();
				Real squaredDepth = mParentNode->getSquaredViewDepth(cam->getLodCamera());
				// Max distance to still render
				Real maxDist = mUpperDistance + rad;
				if (squaredDepth > Math::Sqr(maxDist))
				{
					mBeyondFarDistance = true;
				}
				else
				{
					mBeyondFarDistance = false;
				}
			}
			else
			{
				mBeyondFarDistance = false;
			}

            // Construct event object
            MovableObjectLodChangedEvent evt;
            evt.movableObject = this;
            evt.camera = cam;

            // Notify lod event listeners
            cam->getSceneManager()->_notifyMovableObjectLodChanged(evt);

		}

        mRenderingDisabled = mListener && !mListener->objectRendering(this, cam);
	}
    //-----------------------------------------------------------------------
    void MovableObject::setRenderQueueGroup(uint8 queueID)
    {
		assert(queueID <= RENDER_QUEUE_MAX && "Render queue out of range!");
        mRenderQueueID = queueID;
        mRenderQueueIDSet = true;
    }
    //-----------------------------------------------------------------------
    uint8 MovableObject::getRenderQueueGroup(void) const
    {
        return mRenderQueueID;
    }
    //-----------------------------------------------------------------------
	const Matrix4& MovableObject::_getParentNodeFullTransform(void) const
	{

		if(mParentNode)
		{
			// object attached to a sceneNode
			return mParentNode->_getFullTransform();
		}
        // fallback
        return Matrix4::IDENTITY;
	}
    //-----------------------------------------------------------------------
    const AxisAlignedBox& MovableObject::getWorldBoundingBox(bool derive) const
    {
        if (derive)
        {
            mWorldAABB = this->getBoundingBox();
            mWorldAABB.transformAffine(_getParentNodeFullTransform());
        }

        return mWorldAABB;

    }
    //-----------------------------------------------------------------------
	const Sphere& MovableObject::getWorldBoundingSphere(bool derive) const
	{
		if (derive)
		{
			mWorldBoundingSphere.setRadius(getBoundingRadius());
			mWorldBoundingSphere.setCenter(mParentNode->_getDerivedPosition());
		}
		return mWorldBoundingSphere;
	}
    //-----------------------------------------------------------------------
    const LightList& MovableObject::queryLights(void) const
    {
        // Try listener first
        if (mListener)
        {
            const LightList* lightList =
                mListener->objectQueryLights(this);
            if (lightList)
            {
                return *lightList;
            }
        }

        // Query from parent entity if exists
        if (mParentIsTagPoint)
        {
            TagPoint* tp = static_cast<TagPoint*>(mParentNode);
            return tp->getParentEntity()->queryLights();
        }

        if (mParentNode)
        {
            SceneNode* sn = static_cast<SceneNode*>(mParentNode);

            // Make sure we only update this only if need.
            ulong frame = sn->getCreator()->_getLightsDirtyCounter();
            if (mLightListUpdated != frame)
            {
                mLightListUpdated = frame;

                sn->findLights(mLightList, this->getBoundingRadius(), this->getLightMask());
            }
        }
        else
        {
            mLightList.clear();
        }

        return mLightList;
    }
    //-----------------------------------------------------------------------
    ShadowCaster::ShadowRenderableListIterator MovableObject::getShadowVolumeRenderableIterator(
        ShadowTechnique shadowTechnique, const Light* light,
        HardwareIndexBufferSharedPtr* indexBuffer,
        bool extrudeVertices, Real extrusionDist, unsigned long flags )
    {
        static ShadowRenderableList dummyList;
        return ShadowRenderableListIterator(dummyList.begin(), dummyList.end());
    }
    //-----------------------------------------------------------------------
    const AxisAlignedBox& MovableObject::getLightCapBounds(void) const
    {
        // Same as original bounds
        return getWorldBoundingBox();
    }
    //-----------------------------------------------------------------------
    const AxisAlignedBox& MovableObject::getDarkCapBounds(const Light& light, Real extrusionDist) const
    {
        // Extrude own light cap bounds
        mWorldDarkCapBounds = getLightCapBounds();
        this->extrudeBounds(mWorldDarkCapBounds, light.getAs4DVector(),
            extrusionDist);
        return mWorldDarkCapBounds;

    }
    //-----------------------------------------------------------------------
    Real MovableObject::getPointExtrusionDistance(const Light* l) const
    {
        if (mParentNode)
        {
            return getExtrusionDistance(mParentNode->_getDerivedPosition(), l);
        }
        else
        {
            return 0;
        }
    }
	//-----------------------------------------------------------------------
	uint32 MovableObject::getTypeFlags(void) const
	{
		if (mCreator)
		{
			return mCreator->getTypeFlags();
		}
		else
		{
			return 0xFFFFFFFF;
		}
	}
	//---------------------------------------------------------------------
	void MovableObject::setLightMask(uint32 lightMask)
	{
		this->mLightMask = lightMask;
		//make sure to request a new light list from the scene manager if mask changed
		mLightListUpdated = 0;
	}
	//---------------------------------------------------------------------
	class MORecvShadVisitor : public Renderable::Visitor
	{
	public:
		bool anyReceiveShadows;
		MORecvShadVisitor() : anyReceiveShadows(false)
		{

		}
		void visit(Renderable* rend, ushort lodIndex, bool isDebug,
			Any* pAny = 0)
		{
			anyReceiveShadows = anyReceiveShadows ||
				(!rend->getTechnique() || rend->getTechnique()->getParent()->getReceiveShadows());
		}
	};
	//---------------------------------------------------------------------
	bool MovableObject::getReceivesShadows()
	{
		MORecvShadVisitor visitor;
		visitRenderables(&visitor);
		return visitor.anyReceiveShadows;

	}
	//-----------------------------------------------------------------------
	//-----------------------------------------------------------------------
	MovableObject* MovableObjectFactory::createInstance(
		const String& name, SceneManager* manager,
		const NameValuePairList* params)
	{
		MovableObject* m = createInstanceImpl(name, params);
		m->_notifyCreator(this);
		m->_notifyManager(manager);
		return m;
	}

}

<|endoftext|>


<commit_before>#include <cstdio>
#include <queue>
#include <iostream>

using namespace std;

struct inf
{
    int t, mi, ma, i;
} inp;

struct pri
{
    int n, d, t;
}n, np;

struct vinf
{
    int d, t;
};

struct hp2
{
    bool operator () (pri i, pri j)
    {
        if(i.d==j.d)
        {
            return i.t<j.t;
        }
        else
            return i.d>j.d;
    }
};

int nodes, edges, optim, f, sof, l, r, m;
vector<inf> nlist[1055];
int olist[555];
vinf vis[1055];
priority_queue<pri, vector<pri>, hp2> viser;

bool tester(int far)
{
    //cout<<far<<endl;
    //Try the tying situation. That may help.
    for(int i=1; i<=nodes; i++)
        vis[i].d=-1, vis[i].t=-1;
    np.n=1;
    np.d=0;
    np.t=1;
    vis[np.n].d=0;
    vis[np.n].t=1;
    viser.push(np);
    while (!viser.empty())
    {
        n=viser.top();
        viser.pop();
        if(vis[n.n].d<n.d || vis[n.n].t!=n.t)
            continue;
        if(n.t==-1)
        {
            for(int i=0; i<nlist[n.n].size(); i++)
            {
                if(vis[nlist[n.n][i].t].d==-1 || vis[nlist[n.n][i].t].d>n.d+nlist[n.n][i].ma)
                {
                    vis[nlist[n.n][i].t].d=n.d+nlist[n.n][i].ma;
                    vis[nlist[n.n][i].t].t=-1;
                    np.n=nlist[n.n][i].t;
                    np.d=n.d+nlist[n.n][i].ma;
                    np.t=-1;
                    viser.push(np);
                }
            }
        }
        else if(n.t==0)
        {
            for(int i=0; i<nlist[n.n].size(); i++)
            {
                if(vis[nlist[n.n][i].t].d==-1 || vis[nlist[n.n][i].t].d>=n.d+nlist[n.n][i].mi)
                {
                    vis[nlist[n.n][i].t].d=n.d+nlist[n.n][i].mi;
                    vis[nlist[n.n][i].t].t=0;
                    np.n=nlist[n.n][i].t;
                    np.d=n.d+nlist[n.n][i].mi;
                    np.t=0;
                    viser.push(np);
                }
            }
        }
        else
        {
            for(int i=0; i<nlist[n.n].size(); i++)
            {
                if(n.t>far)
                {
                    //cout<<n.n<<"1"<<nlist[n.n][i].t<<endl;
                    if(vis[nlist[n.n][i].t].d==-1 || vis[nlist[n.n][i].t].d>=n.d+nlist[n.n][i].mi)
                    {
                        vis[nlist[n.n][i].t].d=n.d+nlist[n.n][i].mi;
                        vis[nlist[n.n][i].t].t=0;
                        np.n=nlist[n.n][i].t;
                        np.d=n.d+nlist[n.n][i].mi;
                        np.t=0;
                        viser.push(np);
                    }
                }
                else if(nlist[n.n][i].i==olist[n.t])
                {
                    //cout<<n.n<<"2"<<nlist[n.n][i].t<<endl;
                    if(vis[nlist[n.n][i].t].d==-1 || vis[nlist[n.n][i].t].d>=n.d+nlist[n.n][i].mi)
                    {
                        vis[nlist[n.n][i].t].d=n.d+nlist[n.n][i].mi;
                        vis[nlist[n.n][i].t].t=n.t+1;
                        np.n=nlist[n.n][i].t;
                        np.d=n.d+nlist[n.n][i].mi;
                        np.t=n.t+1;
                        viser.push(np);
                    }
                }
                else
                {
                    //cout<<n.n<<"3"<<nlist[n.n][i].t<<endl;
                    if(vis[nlist[n.n][i].t].d==-1 || vis[nlist[n.n][i].t].d>n.d+nlist[n.n][i].ma)
                    {
                        vis[nlist[n.n][i].t].d=n.d+nlist[n.n][i].ma;
                        vis[nlist[n.n][i].t].t=-1;
                        np.n=nlist[n.n][i].t;
                        np.d=n.d+nlist[n.n][i].ma;
                        np.t=-1;
                        viser.push(np);
                    }
                }
            }
        }
    }
    //0 means short, -1 long, and anything positive means part of the olist
    /*for(int i=1; i<=nodes; i++)
    {
        cout<<i<<" "<<vis[i].d<<" "<<vis[i].t<<endl;
    }*/
    if(vis[2].t==0 || vis[2].t==far+1)
        return true;
    return  false;
}

int main()
{
    scanf("%d%d%d", &nodes, &edges, &optim);
    for(int i=1; i<=edges; i++)
    {
        scanf("%d%d%d%d", &f, &inp.t, &inp.mi, &inp.ma);
        inp.i=i;
        nlist[f].push_back(inp);
    }
    for(int i=1; i<=optim; i++)
        scanf("%d", &olist[i]);
    //Can probably remove this
    l=0;
    r=optim;
    while(l<=r)
    {
        m=(l+r)/2;
        if(tester(m))
        {
            l=m+1;
            sof=m;
        }
        else
            r=m-1;
    }
    if(sof==optim)
        printf("Karel Obscuro le gustan los grafos\n");
    else
        printf("%d\n", olist[sof+1]);
    return 0;
}
/*
 4 5 3
 1 2 100 1000
 1 2 500 1000
 2 2 1 1
 1 2 1000 5000
 1 2 1000 1000
 2 3 3
*/
<commit_msg>Update karel-obscuro-vs-karel.cpp<commit_after>//https://omegaup.com/arena/problem/karel-obscuro-vs-karel

#include <cstdio>
#include <queue>
#include <iostream>

using namespace std;

struct inf
{
    int t, mi, ma, i;
} inp;

struct pri
{
    int n, d, t;
}n, np;

struct vinf
{
    int d, t;
};

struct hp2
{
    bool operator () (pri i, pri j)
    {
        if(i.d==j.d)
        {
            return i.t<j.t;
        }
        else
            return i.d>j.d;
    }
};

int nodes, edges, optim, f, sof, l, r, m;
vector<inf> nlist[1055];
int olist[555];
vinf vis[1055];
priority_queue<pri, vector<pri>, hp2> viser;

bool tester(int far)
{
    //cout<<far<<endl;
    //Try the tying situation. That may help.
    for(int i=1; i<=nodes; i++)
        vis[i].d=-1, vis[i].t=-1;
    np.n=1;
    np.d=0;
    np.t=1;
    vis[np.n].d=0;
    vis[np.n].t=1;
    viser.push(np);
    while (!viser.empty())
    {
        n=viser.top();
        viser.pop();
        if(vis[n.n].d<n.d || vis[n.n].t!=n.t)
            continue;
        if(n.t==-1)
        {
            for(int i=0; i<nlist[n.n].size(); i++)
            {
                if(vis[nlist[n.n][i].t].d==-1 || vis[nlist[n.n][i].t].d>n.d+nlist[n.n][i].ma)
                {
                    vis[nlist[n.n][i].t].d=n.d+nlist[n.n][i].ma;
                    vis[nlist[n.n][i].t].t=-1;
                    np.n=nlist[n.n][i].t;
                    np.d=n.d+nlist[n.n][i].ma;
                    np.t=-1;
                    viser.push(np);
                }
            }
        }
        else if(n.t==0)
        {
            for(int i=0; i<nlist[n.n].size(); i++)
            {
                if(vis[nlist[n.n][i].t].d==-1 || vis[nlist[n.n][i].t].d>=n.d+nlist[n.n][i].mi)
                {
                    vis[nlist[n.n][i].t].d=n.d+nlist[n.n][i].mi;
                    vis[nlist[n.n][i].t].t=0;
                    np.n=nlist[n.n][i].t;
                    np.d=n.d+nlist[n.n][i].mi;
                    np.t=0;
                    viser.push(np);
                }
            }
        }
        else
        {
            for(int i=0; i<nlist[n.n].size(); i++)
            {
                if(n.t>far)
                {
                    //cout<<n.n<<"1"<<nlist[n.n][i].t<<endl;
                    if(vis[nlist[n.n][i].t].d==-1 || vis[nlist[n.n][i].t].d>=n.d+nlist[n.n][i].mi)
                    {
                        vis[nlist[n.n][i].t].d=n.d+nlist[n.n][i].mi;
                        vis[nlist[n.n][i].t].t=0;
                        np.n=nlist[n.n][i].t;
                        np.d=n.d+nlist[n.n][i].mi;
                        np.t=0;
                        viser.push(np);
                    }
                }
                else if(nlist[n.n][i].i==olist[n.t])
                {
                    //cout<<n.n<<"2"<<nlist[n.n][i].t<<endl;
                    if(vis[nlist[n.n][i].t].d==-1 || vis[nlist[n.n][i].t].d>=n.d+nlist[n.n][i].mi)
                    {
                        vis[nlist[n.n][i].t].d=n.d+nlist[n.n][i].mi;
                        vis[nlist[n.n][i].t].t=n.t+1;
                        np.n=nlist[n.n][i].t;
                        np.d=n.d+nlist[n.n][i].mi;
                        np.t=n.t+1;
                        viser.push(np);
                    }
                }
                else
                {
                    //cout<<n.n<<"3"<<nlist[n.n][i].t<<endl;
                    if(vis[nlist[n.n][i].t].d==-1 || vis[nlist[n.n][i].t].d>n.d+nlist[n.n][i].ma)
                    {
                        vis[nlist[n.n][i].t].d=n.d+nlist[n.n][i].ma;
                        vis[nlist[n.n][i].t].t=-1;
                        np.n=nlist[n.n][i].t;
                        np.d=n.d+nlist[n.n][i].ma;
                        np.t=-1;
                        viser.push(np);
                    }
                }
            }
        }
    }
    //0 means short, -1 long, and anything positive means part of the olist
    /*for(int i=1; i<=nodes; i++)
    {
        cout<<i<<" "<<vis[i].d<<" "<<vis[i].t<<endl;
    }*/
    if(vis[2].t==0 || vis[2].t==far+1)
        return true;
    return  false;
}

int main()
{
    scanf("%d%d%d", &nodes, &edges, &optim);
    for(int i=1; i<=edges; i++)
    {
        scanf("%d%d%d%d", &f, &inp.t, &inp.mi, &inp.ma);
        inp.i=i;
        nlist[f].push_back(inp);
    }
    for(int i=1; i<=optim; i++)
        scanf("%d", &olist[i]);
    //Can probably remove this
    l=0;
    r=optim;
    while(l<=r)
    {
        m=(l+r)/2;
        if(tester(m))
        {
            l=m+1;
            sof=m;
        }
        else
            r=m-1;
    }
    if(sof==optim)
        printf("Karel Obscuro le gustan los grafos\n");
    else
        printf("%d\n", olist[sof+1]);
    return 0;
}
/*
 4 5 3
 1 2 100 1000
 1 2 500 1000
 2 2 1 1
 1 2 1000 5000
 1 2 1000 1000
 2 3 3
*/
<|endoftext|>


<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin Core developers
// Copyright (c) 2017-2019 The PIVX developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "validationinterface.h"

#include <unordered_map>
#include <boost/signals2/signal.hpp>

struct ValidationInterfaceConnections {
    boost::signals2::scoped_connection UpdatedBlockTip;
    boost::signals2::scoped_connection SyncTransaction;
    boost::signals2::scoped_connection NotifyTransactionLock;
    boost::signals2::scoped_connection UpdatedTransaction;
    boost::signals2::scoped_connection SetBestChain;
    boost::signals2::scoped_connection Broadcast;
    boost::signals2::scoped_connection BlockChecked;
    boost::signals2::scoped_connection BlockFound;
    boost::signals2::scoped_connection ChainTip;
};

struct MainSignalsInstance {
// XX42    boost::signals2::signal<void(const uint256&)> EraseTransaction;
    /** Notifies listeners of updated block chain tip */
    boost::signals2::signal<void (const CBlockIndex *, const CBlockIndex *, bool fInitialDownload)> UpdatedBlockTip;
    /** A posInBlock value for SyncTransaction which indicates the transaction was conflicted, disconnected, or not in a block */
    static const int SYNC_TRANSACTION_NOT_IN_BLOCK = -1;
    /** Notifies listeners of updated transaction data (transaction, and optionally the block it is found in. */
    boost::signals2::signal<void (const CTransaction &, const CBlockIndex *pindex, int posInBlock)> SyncTransaction;
    /** Notifies listeners of an updated transaction lock without new data. */
    boost::signals2::signal<void (const CTransaction &)> NotifyTransactionLock;
    /** Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible). */
    boost::signals2::signal<bool (const uint256 &)> UpdatedTransaction;
    /** Notifies listeners of a new active block chain. */
    boost::signals2::signal<void (const CBlockLocator &)> SetBestChain;
    /** Tells listeners to broadcast their data. */
    boost::signals2::signal<void (CConnman* connman)> Broadcast;
    /** Notifies listeners of a block validation result */
    boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked;
    /** Notifies listeners that a block has been successfully mined */
    boost::signals2::signal<void (const uint256 &)> BlockFound;

    /** Notifies listeners of a change to the tip of the active block chain. */
    boost::signals2::signal<void (const CBlockIndex *, const CBlock *, Optional<SaplingMerkleTree>)> ChainTip;

    std::unordered_map<CValidationInterface*, ValidationInterfaceConnections> m_connMainSignals;
};

static CMainSignals g_signals;

CMainSignals::CMainSignals() {
    m_internals.reset(new MainSignalsInstance());
}

CMainSignals& GetMainSignals()
{
    return g_signals;
}

void RegisterValidationInterface(CValidationInterface* pwalletIn)
{
    ValidationInterfaceConnections& conns = g_signals.m_internals->m_connMainSignals[pwalletIn];
    conns.UpdatedBlockTip = g_signals.m_internals->UpdatedBlockTip.connect(std::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
    conns.SyncTransaction = g_signals.m_internals->SyncTransaction.connect(std::bind(&CValidationInterface::SyncTransaction, pwalletIn, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
    conns.ChainTip = g_signals.m_internals->ChainTip.connect(std::bind(&CValidationInterface::ChainTip, pwalletIn, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
    conns.NotifyTransactionLock = g_signals.m_internals->NotifyTransactionLock.connect(std::bind(&CValidationInterface::NotifyTransactionLock, pwalletIn, std::placeholders::_1));
    conns.UpdatedTransaction = g_signals.m_internals->UpdatedTransaction.connect(std::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, std::placeholders::_1));
    conns.SetBestChain = g_signals.m_internals->SetBestChain.connect(std::bind(&CValidationInterface::SetBestChain, pwalletIn, std::placeholders::_1));
    conns.Broadcast = g_signals.m_internals->Broadcast.connect(std::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, std::placeholders::_1));
    conns.BlockChecked = g_signals.m_internals->BlockChecked.connect(std::bind(&CValidationInterface::BlockChecked, pwalletIn, std::placeholders::_1, std::placeholders::_2));
    conns.BlockFound = g_signals.m_internals->BlockFound.connect(std::bind(&CValidationInterface::ResetRequestCount, pwalletIn, std::placeholders::_1));
}

void UnregisterValidationInterface(CValidationInterface* pwalletIn)
{
    g_signals.m_internals->m_connMainSignals.erase(pwalletIn);
}

void UnregisterAllValidationInterfaces()
{
    if (!g_signals.m_internals) {
        return;
    }
    g_signals.m_internals->m_connMainSignals.clear();
}

void CMainSignals::UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload) {
    m_internals->UpdatedBlockTip(pindexNew, pindexFork, fInitialDownload);
}

void CMainSignals::SyncTransaction(const CTransaction& tx, const CBlockIndex* pindex, int posInBlock) {
    m_internals->SyncTransaction(tx, pindex, posInBlock);
}

void CMainSignals::NotifyTransactionLock(const CTransaction& tx) {
    m_internals->NotifyTransactionLock(tx);
}

void CMainSignals::UpdatedTransaction(const uint256& hash) {
    m_internals->UpdatedTransaction(hash);
}

void CMainSignals::SetBestChain(const CBlockLocator& locator) {
    m_internals->SetBestChain(locator);
}

void CMainSignals::Broadcast(CConnman* connman) {
    m_internals->Broadcast(connman);
}

void CMainSignals::BlockChecked(const CBlock& block, const CValidationState& state) {
    m_internals->BlockChecked(block, state);
}

void CMainSignals::BlockFound(const uint256& hash) {
    m_internals->BlockFound(hash);
}

void CMainSignals::ChainTip(const CBlockIndex* pindex, const CBlock* block, Optional<SaplingMerkleTree> tree) {
    m_internals->ChainTip(pindex, block, tree);
}<commit_msg>Check m_internals in UnregisterValidationInterface<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin Core developers
// Copyright (c) 2017-2019 The PIVX developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "validationinterface.h"

#include <unordered_map>
#include <boost/signals2/signal.hpp>

struct ValidationInterfaceConnections {
    boost::signals2::scoped_connection UpdatedBlockTip;
    boost::signals2::scoped_connection SyncTransaction;
    boost::signals2::scoped_connection NotifyTransactionLock;
    boost::signals2::scoped_connection UpdatedTransaction;
    boost::signals2::scoped_connection SetBestChain;
    boost::signals2::scoped_connection Broadcast;
    boost::signals2::scoped_connection BlockChecked;
    boost::signals2::scoped_connection BlockFound;
    boost::signals2::scoped_connection ChainTip;
};

struct MainSignalsInstance {
// XX42    boost::signals2::signal<void(const uint256&)> EraseTransaction;
    /** Notifies listeners of updated block chain tip */
    boost::signals2::signal<void (const CBlockIndex *, const CBlockIndex *, bool fInitialDownload)> UpdatedBlockTip;
    /** A posInBlock value for SyncTransaction which indicates the transaction was conflicted, disconnected, or not in a block */
    static const int SYNC_TRANSACTION_NOT_IN_BLOCK = -1;
    /** Notifies listeners of updated transaction data (transaction, and optionally the block it is found in. */
    boost::signals2::signal<void (const CTransaction &, const CBlockIndex *pindex, int posInBlock)> SyncTransaction;
    /** Notifies listeners of an updated transaction lock without new data. */
    boost::signals2::signal<void (const CTransaction &)> NotifyTransactionLock;
    /** Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible). */
    boost::signals2::signal<bool (const uint256 &)> UpdatedTransaction;
    /** Notifies listeners of a new active block chain. */
    boost::signals2::signal<void (const CBlockLocator &)> SetBestChain;
    /** Tells listeners to broadcast their data. */
    boost::signals2::signal<void (CConnman* connman)> Broadcast;
    /** Notifies listeners of a block validation result */
    boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked;
    /** Notifies listeners that a block has been successfully mined */
    boost::signals2::signal<void (const uint256 &)> BlockFound;

    /** Notifies listeners of a change to the tip of the active block chain. */
    boost::signals2::signal<void (const CBlockIndex *, const CBlock *, Optional<SaplingMerkleTree>)> ChainTip;

    std::unordered_map<CValidationInterface*, ValidationInterfaceConnections> m_connMainSignals;
};

static CMainSignals g_signals;

CMainSignals::CMainSignals() {
    m_internals.reset(new MainSignalsInstance());
}

CMainSignals& GetMainSignals()
{
    return g_signals;
}

void RegisterValidationInterface(CValidationInterface* pwalletIn)
{
    ValidationInterfaceConnections& conns = g_signals.m_internals->m_connMainSignals[pwalletIn];
    conns.UpdatedBlockTip = g_signals.m_internals->UpdatedBlockTip.connect(std::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
    conns.SyncTransaction = g_signals.m_internals->SyncTransaction.connect(std::bind(&CValidationInterface::SyncTransaction, pwalletIn, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
    conns.ChainTip = g_signals.m_internals->ChainTip.connect(std::bind(&CValidationInterface::ChainTip, pwalletIn, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
    conns.NotifyTransactionLock = g_signals.m_internals->NotifyTransactionLock.connect(std::bind(&CValidationInterface::NotifyTransactionLock, pwalletIn, std::placeholders::_1));
    conns.UpdatedTransaction = g_signals.m_internals->UpdatedTransaction.connect(std::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, std::placeholders::_1));
    conns.SetBestChain = g_signals.m_internals->SetBestChain.connect(std::bind(&CValidationInterface::SetBestChain, pwalletIn, std::placeholders::_1));
    conns.Broadcast = g_signals.m_internals->Broadcast.connect(std::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, std::placeholders::_1));
    conns.BlockChecked = g_signals.m_internals->BlockChecked.connect(std::bind(&CValidationInterface::BlockChecked, pwalletIn, std::placeholders::_1, std::placeholders::_2));
    conns.BlockFound = g_signals.m_internals->BlockFound.connect(std::bind(&CValidationInterface::ResetRequestCount, pwalletIn, std::placeholders::_1));
}

void UnregisterValidationInterface(CValidationInterface* pwalletIn)
{
    if (g_signals.m_internals) {
        g_signals.m_internals->m_connMainSignals.erase(pwalletIn);
    }
}

void UnregisterAllValidationInterfaces()
{
    if (!g_signals.m_internals) {
        return;
    }
    g_signals.m_internals->m_connMainSignals.clear();
}

void CMainSignals::UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload) {
    m_internals->UpdatedBlockTip(pindexNew, pindexFork, fInitialDownload);
}

void CMainSignals::SyncTransaction(const CTransaction& tx, const CBlockIndex* pindex, int posInBlock) {
    m_internals->SyncTransaction(tx, pindex, posInBlock);
}

void CMainSignals::NotifyTransactionLock(const CTransaction& tx) {
    m_internals->NotifyTransactionLock(tx);
}

void CMainSignals::UpdatedTransaction(const uint256& hash) {
    m_internals->UpdatedTransaction(hash);
}

void CMainSignals::SetBestChain(const CBlockLocator& locator) {
    m_internals->SetBestChain(locator);
}

void CMainSignals::Broadcast(CConnman* connman) {
    m_internals->Broadcast(connman);
}

void CMainSignals::BlockChecked(const CBlock& block, const CValidationState& state) {
    m_internals->BlockChecked(block, state);
}

void CMainSignals::BlockFound(const uint256& hash) {
    m_internals->BlockFound(hash);
}

void CMainSignals::ChainTip(const CBlockIndex* pindex, const CBlock* block, Optional<SaplingMerkleTree> tree) {
    m_internals->ChainTip(pindex, block, tree);
}<|endoftext|>