<commit_before>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//
// $Id:

#include <BALL/VIEW/KERNEL/connectionObject.h>
#include <BALL/VIEW/KERNEL/message.h>

namespace BALL
{
	namespace VIEW
	{
		using std::ostream;

ConnectionObject::ConnectionObject()
: processing_message_queue_(false),
	message_queue_(),
	parent_(0),
	children_connection_objects_()
{
}

ConnectionObject::~ConnectionObject()
{
	#ifdef BALL_VIEW_DEBUG
		Log.info() << "Destructing object " << (void *)this
							 << " of class ConnectionObject" << std::endl;
	#endif

	destroy();
}

void ConnectionObject::clear()
{
	// clear the message queue
	list<Message*>::iterator message_iterator;
	for(message_iterator = message_queue_.begin();
			message_iterator != message_queue_.end();
			++message_iterator)
	{
		// order of this if-statement is important
		// only root has the right to delete deletable messages
		if (this == getRoot()
				&& (*message_iterator)->isDeletable())
		{
			delete *message_iterator;
		}
	}

	message_queue_.clear();

	// unregister this from parent if parent exists
	if (parent_)
	{
		parent_->unregisterConnectionObject(*this);
		clearParent_();
	}

	// unregister all children
	list<ConnectionObject*>::iterator list_iterator;

	for(list_iterator = children_connection_objects_.begin();
			list_iterator != children_connection_objects_.end();
			++list_iterator)
	{
		(*list_iterator)->clearParent_();
	}

	children_connection_objects_.clear();
}

void ConnectionObject::destroy()
{
	clear();
}

void ConnectionObject::registerConnectionObject(ConnectionObject &object)
{
	// register only once
	if (isConnectionObjectRegistered(object)) return;

	children_connection_objects_.push_back(&object);
	object.setParent_(*this);
}

void ConnectionObject::unregisterConnectionObject(ConnectionObject &object)
{
	// search object in list
	// if inserted cut connection between them
	list<ConnectionObject*>::iterator list_iterator;
	list<ConnectionObject*>::iterator to_be_deleted_iterator
		= children_connection_objects_.end();

	for(list_iterator = children_connection_objects_.begin();
			list_iterator != children_connection_objects_.end();
			++list_iterator)
	{
		if (*list_iterator == &object)
		{
			to_be_deleted_iterator = list_iterator;
			(*list_iterator)->clearParent_();
			break;
		}
	}

	// if there is something to delete, delete it
	if (to_be_deleted_iterator != children_connection_objects_.end())
	{
		children_connection_objects_.erase(to_be_deleted_iterator);
	}
}

bool ConnectionObject::isConnectionObjectRegistered(const ConnectionObject &object)
{
	// search object in list
	// if already inserted return true else return false
	list<ConnectionObject*>::const_iterator list_iterator;

	for(list_iterator = children_connection_objects_.begin();
			list_iterator != children_connection_objects_.end();
			++list_iterator)
	{
		if (*list_iterator == &object) return true;
	}

	return false;
}

ConnectionObject *ConnectionObject::getRoot()
{
	ConnectionObject *object = this;

	while (object->getParent())
	{
		object = object->getParent();
	}

	return object;
}

void ConnectionObject::onNotify(Message * /* message */)
{
}

bool ConnectionObject::isValid() const
{
	// check all children if parent will be this
	list<ConnectionObject*>::const_iterator list_iterator;

	for(list_iterator = children_connection_objects_.begin();
			list_iterator != children_connection_objects_.end();
			++list_iterator)
	{
		if (!(*list_iterator)->ConnectionObject::isValid()) return false;
	}

	//has parent a connection to this child
	if (parent_)
	{
		return parent_->isConnectionObjectRegistered(*this);
	}

	return true;
}

void ConnectionObject::dump(ostream& s, Size depth) const
{
	BALL_DUMP_STREAM_PREFIX(s);

	BALL_DUMP_DEPTH(s, depth);
	BALL_DUMP_HEADER(s, this, this);

	BALL_DUMP_DEPTH(s, depth);
	s << "size of message queue: " << message_queue_.size() << std::endl;

	BALL_DUMP_DEPTH(s, depth);
	s << "parent: " << (void*)parent_ << std::endl;

	BALL_DUMP_DEPTH(s, depth);
	s << "number of registered objects: " << children_connection_objects_.size() << std::endl;
	list<ConnectionObject*>::const_iterator it = children_connection_objects_.begin();
	for (Position p = 0; p < children_connection_objects_.size(); p++)
	{
		s << String(p) + ": " << *it  << "  " << typeid(**it).name() << std::endl;
		(*it)->dump(s, depth +1);
		it++;
	}

	BALL_DUMP_STREAM_SUFFIX(s);
}

void ConnectionObject::notify_(Message *message)
{
	message->setSender(this);
	getRoot()->onNotify_(message);
}

void ConnectionObject::notify_(Message &message)
{
	message.setSender(this);
	getRoot()->onNotify_(&message);
}

void ConnectionObject::onNotify_(Message* message)
{
	// insert Message into queue (last position)
	message_queue_.push_back(message);

	// if already processing message queue => exit
	if (processing_message_queue_) return;

	processing_message_queue_ = true;

	// process messages in queue
	while (message_queue_.size())
	{
		// get first message
		Message *current_message = *(message_queue_.begin());

		// delete first message from queue
		message_queue_.pop_front();

		// process message, but not if sender = this
		if (current_message->getSender() != this)
		{
			onNotify(current_message);
		}

		// notify all children
		list<ConnectionObject *>::iterator list_iterator;

		for(list_iterator = children_connection_objects_.begin();
				list_iterator != children_connection_objects_.end();
				++list_iterator)
		{
			(*list_iterator)->onNotify_(current_message);
		}

		// delete message if it is deletable and this == root (only root has the right to delete messages)
		if (this == getRoot() &&
				current_message->isDeletable())
		{
			delete current_message;
		}
	}

	processing_message_queue_ = false;
}

#		ifdef BALL_NO_INLINE_FUNCTIONS
#			include <BALL/VIEW/KERNEL/connectionObject.iC>
#		endif

} } // namespace
<commit_msg>Style fixes to connectionObject.<commit_after>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//

#include <BALL/VIEW/KERNEL/connectionObject.h>
#include <BALL/VIEW/KERNEL/message.h>

namespace BALL
{
	namespace VIEW
	{
		using std::ostream;

ConnectionObject::ConnectionObject()
: processing_message_queue_(false),
	message_queue_(),
	parent_(0),
	children_connection_objects_()
{
}

ConnectionObject::~ConnectionObject()
{
	#ifdef BALL_VIEW_DEBUG
		Log.info() << "Destructing object " << (void *)this
							 << " of class ConnectionObject" << std::endl;
	#endif

	destroy();
}

void ConnectionObject::clear()
{
	// clear the message queue
	list<Message*>::iterator message_iterator;
	for(message_iterator = message_queue_.begin();
			message_iterator != message_queue_.end();
			++message_iterator)
	{
		// order of this if-statement is important
		// only root has the right to delete deletable messages
		if (this == getRoot()
				&& (*message_iterator)->isDeletable())
		{
			delete *message_iterator;
		}
	}

	message_queue_.clear();

	// unregister this from parent if parent exists
	if (parent_)
	{
		parent_->unregisterConnectionObject(*this);
		clearParent_();
	}

	// unregister all children
	list<ConnectionObject*>::iterator list_iterator;

	for(list_iterator = children_connection_objects_.begin();
			list_iterator != children_connection_objects_.end();
			++list_iterator)
	{
		(*list_iterator)->clearParent_();
	}

	children_connection_objects_.clear();
}

void ConnectionObject::destroy()
{
	clear();
}

void ConnectionObject::registerConnectionObject(ConnectionObject &object)
{
	// register only once
	if (isConnectionObjectRegistered(object)) return;

	children_connection_objects_.push_back(&object);
	object.setParent_(*this);
}

void ConnectionObject::unregisterConnectionObject(ConnectionObject &object)
{
	// search object in list
	// if inserted cut connection between them
	list<ConnectionObject*>::iterator list_iterator;
	list<ConnectionObject*>::iterator to_be_deleted_iterator
		= children_connection_objects_.end();

	for(list_iterator = children_connection_objects_.begin();
			list_iterator != children_connection_objects_.end();
			++list_iterator)
	{
		if (*list_iterator == &object)
		{
			to_be_deleted_iterator = list_iterator;
			(*list_iterator)->clearParent_();
			break;
		}
	}

	// if there is something to delete, delete it
	if (to_be_deleted_iterator != children_connection_objects_.end())
	{
		children_connection_objects_.erase(to_be_deleted_iterator);
	}
}

bool ConnectionObject::isConnectionObjectRegistered(const ConnectionObject &object)
{
	// search object in list
	// if already inserted return true else return false
	list<ConnectionObject*>::const_iterator list_iterator;

	for(list_iterator = children_connection_objects_.begin();
			list_iterator != children_connection_objects_.end();
			++list_iterator)
	{
		if (*list_iterator == &object) return true;
	}

	return false;
}

ConnectionObject *ConnectionObject::getRoot()
{
	ConnectionObject *object = this;

	while (object->getParent())
	{
		object = object->getParent();
	}

	return object;
}

void ConnectionObject::onNotify(Message * /* message */)
{
}

bool ConnectionObject::isValid() const
{
	// check all children if parent will be this
	list<ConnectionObject*>::const_iterator list_iterator;

	for(list_iterator = children_connection_objects_.begin();
			list_iterator != children_connection_objects_.end();
			++list_iterator)
	{
		if (!(*list_iterator)->ConnectionObject::isValid()) return false;
	}

	// has parent a connection to this child
	if (parent_)
	{
		return parent_->isConnectionObjectRegistered(*this);
	}

	return true;
}

void ConnectionObject::dump(ostream& s, Size depth) const
{
	BALL_DUMP_STREAM_PREFIX(s);

	BALL_DUMP_DEPTH(s, depth);
	BALL_DUMP_HEADER(s, this, this);

	BALL_DUMP_DEPTH(s, depth);
	s << "size of message queue: " << message_queue_.size() << std::endl;

	BALL_DUMP_DEPTH(s, depth);
	s << "parent: " << (void*)parent_ << std::endl;

	BALL_DUMP_DEPTH(s, depth);
	s << "number of registered objects: " << children_connection_objects_.size() << std::endl;
	list<ConnectionObject*>::const_iterator it = children_connection_objects_.begin();
	for (Position p = 0; p < children_connection_objects_.size(); p++)
	{
		s << String(p) + ": " << *it  << "  " << typeid(**it).name() << std::endl;
		(*it)->dump(s, depth +1);
		it++;
	}

	BALL_DUMP_STREAM_SUFFIX(s);
}

void ConnectionObject::notify_(Message *message)
{
	message->setSender(this);
	getRoot()->onNotify_(message);
}

void ConnectionObject::notify_(Message &message)
{
	message.setSender(this);
	getRoot()->onNotify_(&message);
}

void ConnectionObject::onNotify_(Message* message)
{
	// insert Message into queue (last position)
	message_queue_.push_back(message);

	// if already processing message queue => exit
	if (processing_message_queue_) return;

	processing_message_queue_ = true;

	// process messages in queue
	while (message_queue_.size())
	{
		// get first message
		Message *current_message = *(message_queue_.begin());

		// delete first message from queue
		message_queue_.pop_front();

		// process message, but not if sender = this
		if (current_message->getSender() != this)
		{
			onNotify(current_message);
		}

		// notify all children
		list<ConnectionObject *>::iterator list_iterator;

		for(list_iterator = children_connection_objects_.begin();
				list_iterator != children_connection_objects_.end();
				++list_iterator)
		{
			(*list_iterator)->onNotify_(current_message);
		}

		// delete message if it is deletable and this == root (only root has the right to delete messages)
		if (this == getRoot() &&
				current_message->isDeletable())
		{
			delete current_message;
		}
	}

	processing_message_queue_ = false;
}

#		ifdef BALL_NO_INLINE_FUNCTIONS
#			include <BALL/VIEW/KERNEL/connectionObject.iC>
#		endif

} } // namespace
<|endoftext|>


<commit_before>
/*
    pbrt source code is Copyright(c) 1998-2016
                        Matt Pharr, Greg Humphreys, and Wenzel Jakob.

    This file is part of pbrt.

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are
    met:

    - Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.

    - Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
    IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
    TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

 */

// integrators/volpath.cpp*
#include "integrators/volpath.h"
#include "bssrdf.h"
#include "camera.h"
#include "film.h"
#include "interaction.h"
#include "paramset.h"
#include "scene.h"
#include "stats.h"

namespace pbrt {

STAT_FLOAT_DISTRIBUTION("Integrator/Path length", pathLength);
STAT_COUNTER("Integrator/Volume interactions", volumeInteractions);
STAT_COUNTER("Integrator/Surface interactions", surfaceInteractions);

// VolPathIntegrator Method Definitions
void VolPathIntegrator::Preprocess(const Scene &scene, Sampler &sampler) {
    lightDistribution =
        CreateLightSampleDistribution(lightSampleStrategy, scene);
}

Spectrum VolPathIntegrator::Li(const RayDifferential &r, const Scene &scene,
                               Sampler &sampler, MemoryArena &arena,
                               int depth) const {
    ProfilePhase p(Prof::SamplerIntegratorLi);
    Spectrum L(0.f), beta(1.f);
    RayDifferential ray(r);
    bool specularBounce = false;
    int bounces;
    // Added after book publication: etaScale tracks the accumulated effect
    // of radiance scaling due to rays passing through refractive
    // boundaries (see the derivation on p. 527 of the third edition). We
    // track this value in order to remove it from beta when we apply
    // Russian roulette; this is worthwhile, since it lets us sometimes
    // avoid terminating refracted rays that are about to be refracted back
    // out of a medium and thus have their beta value increased.
    Float etaScale = 1;

    for (bounces = 0;; ++bounces) {
        // Intersect _ray_ with scene and store intersection in _isect_
        SurfaceInteraction isect;
        bool foundIntersection = scene.Intersect(ray, &isect);

        // Sample the participating medium, if present
        MediumInteraction mi;
        if (ray.medium) beta *= ray.medium->Sample(ray, sampler, arena, &mi);
        if (beta.IsBlack()) break;

        // Handle an interaction with a medium or a surface
        if (mi.IsValid()) {
            // Terminate path if ray escaped or _maxDepth_ was reached
            if (bounces >= maxDepth) break;

            ++volumeInteractions;
            // Handle scattering at point in medium for volumetric path tracer
            const Distribution1D *lightDistrib =
                lightDistribution->Lookup(mi.p);
            L += beta * UniformSampleOneLight(mi, scene, arena, sampler, true,
                                              lightDistrib);

            Vector3f wo = -ray.d, wi;
            mi.phase->Sample_p(wo, &wi, sampler.Get2D());
            ray = mi.SpawnRay(wi);
            specularBounce = false;
        } else {
            ++surfaceInteractions;
            // Handle scattering at point on surface for volumetric path tracer

            // Possibly add emitted light at intersection
            if (bounces == 0 || specularBounce) {
                // Add emitted light at path vertex or from the environment
                if (foundIntersection)
                    L += beta * isect.Le(-ray.d);
                else
                    for (const auto &light : scene.infiniteLights)
                        L += beta * light->Le(ray);
            }

            // Terminate path if ray escaped or _maxDepth_ was reached
            if (!foundIntersection || bounces >= maxDepth) break;

            // Compute scattering functions and skip over medium boundaries
            isect.ComputeScatteringFunctions(ray, arena, true);
            if (!isect.bsdf) {
                ray = isect.SpawnRay(ray.d);
                bounces--;
                continue;
            }

            // Sample illumination from lights to find attenuated path
            // contribution
            const Distribution1D *lightDistrib =
                lightDistribution->Lookup(isect.p);
            L += beta * UniformSampleOneLight(isect, scene, arena, sampler,
                                              true, lightDistrib);

            // Sample BSDF to get new path direction
            Vector3f wo = -ray.d, wi;
            Float pdf;
            BxDFType flags;
            Spectrum f = isect.bsdf->Sample_f(wo, &wi, sampler.Get2D(), &pdf,
                                              BSDF_ALL, &flags);
            if (f.IsBlack() || pdf == 0.f) break;
            beta *= f * AbsDot(wi, isect.shading.n) / pdf;
            DCHECK(std::isinf(beta.y()) == false);
            specularBounce = (flags & BSDF_SPECULAR) != 0;
            if ((flags & BSDF_SPECULAR) && (flags & BSDF_TRANSMISSION)) {
                Float eta = isect.bsdf->eta;
                // Update the term that tracks radiance scaling for refraction
                // depending on whether the ray is entering or leaving the
                // medium.
                etaScale *=
                    (Dot(wo, isect.n) > 0) ? (eta * eta) : 1 / (eta * eta);
            }
            ray = isect.SpawnRay(wi);

            // Account for attenuated subsurface scattering, if applicable
            if (isect.bssrdf && (flags & BSDF_TRANSMISSION)) {
                // Importance sample the BSSRDF
                SurfaceInteraction pi;
                Spectrum S = isect.bssrdf->Sample_S(
                    scene, sampler.Get1D(), sampler.Get2D(), arena, &pi, &pdf);
                DCHECK(std::isinf(beta.y()) == false);
                if (S.IsBlack() || pdf == 0) break;
                beta *= S / pdf;

                // Account for the attenuated direct subsurface scattering
                // component
                L += beta *
                     UniformSampleOneLight(pi, scene, arena, sampler, true,
                                           lightDistribution->Lookup(pi.p));

                // Account for the indirect subsurface scattering component
                Spectrum f = pi.bsdf->Sample_f(pi.wo, &wi, sampler.Get2D(),
                                               &pdf, BSDF_ALL, &flags);
                if (f.IsBlack() || pdf == 0) break;
                beta *= f * AbsDot(wi, pi.shading.n) / pdf;
                DCHECK(std::isinf(beta.y()) == false);
                specularBounce = (flags & BSDF_SPECULAR) != 0;
                ray = pi.SpawnRay(wi);
            }
        }

        // Possibly terminate the path with Russian roulette
        // Factor out radiance scaling due to refraction in rrBeta.
        Spectrum rrBeta = beta * etaScale;
        if (rrBeta.MaxComponentValue() < rrThreshold && bounces > 3) {
            Float q = std::max((Float).05, 1 - rrBeta.MaxComponentValue());
            if (sampler.Get1D() < q) break;
            beta /= 1 - q;
            DCHECK(std::isinf(beta.y()) == false);
        }
    }
    ReportValue(pathLength, bounces);
    return L;
}

VolPathIntegrator *CreateVolPathIntegrator(
    const ParamSet &params, std::shared_ptr<Sampler> sampler,
    std::shared_ptr<const Camera> camera) {
    int maxDepth = params.FindOneInt("maxdepth", 5);
    int np;
    const int *pb = params.FindInt("pixelbounds", &np);
    Bounds2i pixelBounds = camera->film->GetSampleBounds();
    if (pb) {
        if (np != 4)
            Error("Expected four values for \"pixelbounds\" parameter. Got %d.",
                  np);
        else {
            pixelBounds = Intersect(pixelBounds,
                                    Bounds2i{{pb[0], pb[2]}, {pb[1], pb[3]}});
            if (pixelBounds.Area() == 0)
                Error("Degenerate \"pixelbounds\" specified.");
        }
    }
    Float rrThreshold = params.FindOneFloat("rrthreshold", 1.);
    std::string lightStrategy =
        params.FindOneString("lightsamplestrategy", "spatial");
    return new VolPathIntegrator(maxDepth, camera, sampler, pixelBounds,
                                 rrThreshold, lightStrategy);
}

}  // namespace pbrt
<commit_msg>Record VolPathIntegrator path length with an integer distribution<commit_after>
/*
    pbrt source code is Copyright(c) 1998-2016
                        Matt Pharr, Greg Humphreys, and Wenzel Jakob.

    This file is part of pbrt.

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are
    met:

    - Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.

    - Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
    IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
    TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

 */

// integrators/volpath.cpp*
#include "integrators/volpath.h"
#include "bssrdf.h"
#include "camera.h"
#include "film.h"
#include "interaction.h"
#include "paramset.h"
#include "scene.h"
#include "stats.h"

namespace pbrt {

STAT_INT_DISTRIBUTION("Integrator/Path length", pathLength);
STAT_COUNTER("Integrator/Volume interactions", volumeInteractions);
STAT_COUNTER("Integrator/Surface interactions", surfaceInteractions);

// VolPathIntegrator Method Definitions
void VolPathIntegrator::Preprocess(const Scene &scene, Sampler &sampler) {
    lightDistribution =
        CreateLightSampleDistribution(lightSampleStrategy, scene);
}

Spectrum VolPathIntegrator::Li(const RayDifferential &r, const Scene &scene,
                               Sampler &sampler, MemoryArena &arena,
                               int depth) const {
    ProfilePhase p(Prof::SamplerIntegratorLi);
    Spectrum L(0.f), beta(1.f);
    RayDifferential ray(r);
    bool specularBounce = false;
    int bounces;
    // Added after book publication: etaScale tracks the accumulated effect
    // of radiance scaling due to rays passing through refractive
    // boundaries (see the derivation on p. 527 of the third edition). We
    // track this value in order to remove it from beta when we apply
    // Russian roulette; this is worthwhile, since it lets us sometimes
    // avoid terminating refracted rays that are about to be refracted back
    // out of a medium and thus have their beta value increased.
    Float etaScale = 1;

    for (bounces = 0;; ++bounces) {
        // Intersect _ray_ with scene and store intersection in _isect_
        SurfaceInteraction isect;
        bool foundIntersection = scene.Intersect(ray, &isect);

        // Sample the participating medium, if present
        MediumInteraction mi;
        if (ray.medium) beta *= ray.medium->Sample(ray, sampler, arena, &mi);
        if (beta.IsBlack()) break;

        // Handle an interaction with a medium or a surface
        if (mi.IsValid()) {
            // Terminate path if ray escaped or _maxDepth_ was reached
            if (bounces >= maxDepth) break;

            ++volumeInteractions;
            // Handle scattering at point in medium for volumetric path tracer
            const Distribution1D *lightDistrib =
                lightDistribution->Lookup(mi.p);
            L += beta * UniformSampleOneLight(mi, scene, arena, sampler, true,
                                              lightDistrib);

            Vector3f wo = -ray.d, wi;
            mi.phase->Sample_p(wo, &wi, sampler.Get2D());
            ray = mi.SpawnRay(wi);
            specularBounce = false;
        } else {
            ++surfaceInteractions;
            // Handle scattering at point on surface for volumetric path tracer

            // Possibly add emitted light at intersection
            if (bounces == 0 || specularBounce) {
                // Add emitted light at path vertex or from the environment
                if (foundIntersection)
                    L += beta * isect.Le(-ray.d);
                else
                    for (const auto &light : scene.infiniteLights)
                        L += beta * light->Le(ray);
            }

            // Terminate path if ray escaped or _maxDepth_ was reached
            if (!foundIntersection || bounces >= maxDepth) break;

            // Compute scattering functions and skip over medium boundaries
            isect.ComputeScatteringFunctions(ray, arena, true);
            if (!isect.bsdf) {
                ray = isect.SpawnRay(ray.d);
                bounces--;
                continue;
            }

            // Sample illumination from lights to find attenuated path
            // contribution
            const Distribution1D *lightDistrib =
                lightDistribution->Lookup(isect.p);
            L += beta * UniformSampleOneLight(isect, scene, arena, sampler,
                                              true, lightDistrib);

            // Sample BSDF to get new path direction
            Vector3f wo = -ray.d, wi;
            Float pdf;
            BxDFType flags;
            Spectrum f = isect.bsdf->Sample_f(wo, &wi, sampler.Get2D(), &pdf,
                                              BSDF_ALL, &flags);
            if (f.IsBlack() || pdf == 0.f) break;
            beta *= f * AbsDot(wi, isect.shading.n) / pdf;
            DCHECK(std::isinf(beta.y()) == false);
            specularBounce = (flags & BSDF_SPECULAR) != 0;
            if ((flags & BSDF_SPECULAR) && (flags & BSDF_TRANSMISSION)) {
                Float eta = isect.bsdf->eta;
                // Update the term that tracks radiance scaling for refraction
                // depending on whether the ray is entering or leaving the
                // medium.
                etaScale *=
                    (Dot(wo, isect.n) > 0) ? (eta * eta) : 1 / (eta * eta);
            }
            ray = isect.SpawnRay(wi);

            // Account for attenuated subsurface scattering, if applicable
            if (isect.bssrdf && (flags & BSDF_TRANSMISSION)) {
                // Importance sample the BSSRDF
                SurfaceInteraction pi;
                Spectrum S = isect.bssrdf->Sample_S(
                    scene, sampler.Get1D(), sampler.Get2D(), arena, &pi, &pdf);
                DCHECK(std::isinf(beta.y()) == false);
                if (S.IsBlack() || pdf == 0) break;
                beta *= S / pdf;

                // Account for the attenuated direct subsurface scattering
                // component
                L += beta *
                     UniformSampleOneLight(pi, scene, arena, sampler, true,
                                           lightDistribution->Lookup(pi.p));

                // Account for the indirect subsurface scattering component
                Spectrum f = pi.bsdf->Sample_f(pi.wo, &wi, sampler.Get2D(),
                                               &pdf, BSDF_ALL, &flags);
                if (f.IsBlack() || pdf == 0) break;
                beta *= f * AbsDot(wi, pi.shading.n) / pdf;
                DCHECK(std::isinf(beta.y()) == false);
                specularBounce = (flags & BSDF_SPECULAR) != 0;
                ray = pi.SpawnRay(wi);
            }
        }

        // Possibly terminate the path with Russian roulette
        // Factor out radiance scaling due to refraction in rrBeta.
        Spectrum rrBeta = beta * etaScale;
        if (rrBeta.MaxComponentValue() < rrThreshold && bounces > 3) {
            Float q = std::max((Float).05, 1 - rrBeta.MaxComponentValue());
            if (sampler.Get1D() < q) break;
            beta /= 1 - q;
            DCHECK(std::isinf(beta.y()) == false);
        }
    }
    ReportValue(pathLength, bounces);
    return L;
}

VolPathIntegrator *CreateVolPathIntegrator(
    const ParamSet &params, std::shared_ptr<Sampler> sampler,
    std::shared_ptr<const Camera> camera) {
    int maxDepth = params.FindOneInt("maxdepth", 5);
    int np;
    const int *pb = params.FindInt("pixelbounds", &np);
    Bounds2i pixelBounds = camera->film->GetSampleBounds();
    if (pb) {
        if (np != 4)
            Error("Expected four values for \"pixelbounds\" parameter. Got %d.",
                  np);
        else {
            pixelBounds = Intersect(pixelBounds,
                                    Bounds2i{{pb[0], pb[2]}, {pb[1], pb[3]}});
            if (pixelBounds.Area() == 0)
                Error("Degenerate \"pixelbounds\" specified.");
        }
    }
    Float rrThreshold = params.FindOneFloat("rrthreshold", 1.);
    std::string lightStrategy =
        params.FindOneString("lightsamplestrategy", "spatial");
    return new VolPathIntegrator(maxDepth, camera, sampler, pixelBounds,
                                 rrThreshold, lightStrategy);
}

}  // namespace pbrt
<|endoftext|>


<commit_before>/*
    Driver program; runs compiler in an interactive mode.

*/

#include <iostream>
#include <sstream>
#include <string>
#include "compiler.hh"

int main () {

    const char QUIT_CHAR = '$';
    const std::string PROMPT = std::string("Enter a line to be compiled ('") + QUIT_CHAR + "' to quit):\n";
    std::stringstream compiler_input(std::ios::in|std::ios::out);
    ds_compiler::Compiler my_compiler(&compiler_input, &std::cout);

    std::string input_line = "";
    while (std::cout << PROMPT                      //TODO - figure out why this needs two line breaks on first call.
            && std::getline(std::cin, input_line)
            && std::cin.peek() != QUIT_CHAR) {
        compiler_input << input_line;
        my_compiler.compile_intermediate();
    }

    return 0;
}

<commit_msg>Fixed issue in interactive_compiler where two lines were needed for first input<commit_after>/*
    Driver program; runs compiler in an interactive mode.

*/

#include <iostream>
#include <sstream>
#include <string>
#include "compiler.hh"

int main () {

    const char QUIT_CHAR = '$';
    const std::string PROMPT = std::string("Enter a line to be compiled ('") + QUIT_CHAR + "' to quit):\n";
    std::stringstream compiler_input(std::ios::in|std::ios::out);
    ds_compiler::Compiler my_compiler(&compiler_input, &std::cout);

    std::string input_line = "";
    while (std::cout << PROMPT
            && std::getline(std::cin, input_line)) {

        if (input_line.at(0) == QUIT_CHAR) {
            break;
        }
        compiler_input << input_line;
        my_compiler.compile_intermediate();
    }

    return 0;
}

<|endoftext|>


<commit_before>#include <pangolin/platform.h>

#include <fstream>
#include <pangolin/image/typed_image.h>

#ifdef HAVE_OPENEXR
#include <ImfChannelList.h>
#include <ImfInputFile.h>
#include <ImfOutputFile.h>
#include <ImfIO.h>
#endif // HAVE_OPENEXR

namespace pangolin {

#ifdef HAVE_OPENEXR
Imf::PixelType OpenEXRPixelType(int channel_bits)
{
    if( channel_bits == 16 ) {
        return Imf::PixelType::HALF;
    }else if( channel_bits == 32 ) {
        return Imf::PixelType::FLOAT;
    }else{
        throw std::runtime_error("Unsupported OpenEXR Pixel Type.");
    }
}

void SetOpenEXRChannels(Imf::ChannelList& ch, const pangolin::PixelFormat& fmt)
{
    const char* CHANNEL_NAMES[] = {"R","G","B","A"};
    for(size_t c=0; c < fmt.channels; ++c) {
        ch.insert( CHANNEL_NAMES[c], Imf::Channel(OpenEXRPixelType(fmt.channel_bits[c])) );
    }
}

class StdIStream: public Imf::IStream
{
  public:
    StdIStream (std::istream &is):
        Imf::IStream ("stream"),
        _is (&is)
    {
    }

    virtual bool read (char c[/*n*/], int n)
    {
        if (!*_is)
            throw std::runtime_error("Unexpected end of file.");
        _is->read (c, n);
        if (_is->gcount() < n)
        {
            throw std::runtime_error("Early end of file");
            return false;
        }
        return true;
    }

    virtual Imf::Int64 tellg ()
    {
        return std::streamoff (_is->tellg());
    }

    virtual void seekg (Imf::Int64 pos)
    {
        _is->seekg (pos);
    }

    virtual void clear ()
    {
        _is->clear();
    }

  private:
    std::istream *	_is;
};

#endif //HAVE_OPENEXR

TypedImage LoadExr(std::istream& source)
{
#ifdef HAVE_OPENEXR
    StdIStream istream(source);
    Imf::InputFile file(istream);
    Imath::Box2i dw = file.header().dataWindow();
    int width = dw.max.x - dw.min.x + 1;
    int height = dw.max.y - dw.min.y + 1;

    // assume RGBA format for now
    PixelFormat format = PixelFormatFromString("RGBA128F");
    TypedImage img(width, height, format, width*sizeof(float)*4);

    char *imgBase = (char *) img.ptr - (dw.min.x + dw.min.y * width)*sizeof(float)*4;

    Imf::FrameBuffer fb;
    fb.insert("R", Imf::Slice(
                    Imf::FLOAT, imgBase,
                    sizeof(float) * 4,
                    sizeof(float) * 4 * width,
                    1, 1,
                    0.0));

    fb.insert("G", Imf::Slice(
                    Imf::FLOAT, imgBase + sizeof(float),
                    sizeof(float) * 4,
                    sizeof(float) * 4 * width,
                    1, 1,
                    0.0));

    fb.insert("B", Imf::Slice(
                    Imf::FLOAT, imgBase + sizeof(float)*2,
                    sizeof(float) * 4,
                    sizeof(float) * 4 * width,
                    1, 1,
                    0.0));

    fb.insert("A", Imf::Slice(
                    Imf::FLOAT, imgBase + sizeof(float)*3,
                    sizeof(float) * 4,
                    sizeof(float) * 4 * width,
                    1, 1,
                    0.0));

    file.setFrameBuffer(fb);
    file.readPixels(dw.min.y, dw.max.y);

    return img;
#else
    PANGOLIN_UNUSED(source);
    throw std::runtime_error("Rebuild Pangolin for EXR support.");
#endif //HAVE_OPENEXR
}

void SaveExr(const Image<unsigned char>& image_in, const pangolin::PixelFormat& fmt, const std::string& filename, bool top_line_first)
{
#ifdef HAVE_OPENEXR
    ManagedImage<unsigned char> flip_image;
    Image<unsigned char> image;

    if(top_line_first) {
        image = image_in;
    }else{
        flip_image.Reinitialise(image_in.pitch,image_in.h);
        for(size_t y=0; y<image_in.h; ++y) {
            std::memcpy(flip_image.RowPtr(y), image_in.RowPtr(y), image_in.pitch);
        }
        image = flip_image;
    }

    Imf::Header header (image.w, image.h);
    SetOpenEXRChannels(header.channels(), fmt);

    Imf::OutputFile file (filename.c_str(), header);
    Imf::FrameBuffer frameBuffer;

    int ch=0;
    size_t ch_bits = 0;
    for(Imf::ChannelList::Iterator it = header.channels().begin(); it != header.channels().end(); ++it)
    {
        frameBuffer.insert(
            it.name(),
            Imf::Slice(
                it.channel().type,
                (char*)image.ptr + ch_bits/8,
                fmt.channel_bits[ch]/8,
                image.pitch
            )
        );

        ch_bits += fmt.channel_bits[ch++];
    }

    file.setFrameBuffer(frameBuffer);
    file.writePixels(image.h);

#else
    PANGOLIN_UNUSED(image_in);
    PANGOLIN_UNUSED(fmt);
    PANGOLIN_UNUSED(filename);
    PANGOLIN_UNUSED(top_line_first);
    throw std::runtime_error("EXR Support not enabled. Please rebuild Pangolin.");
#endif // HAVE_OPENEXR
}

}
<commit_msg>Support 1, 3 and 4 channel OpenEXR files. (#410)<commit_after>#include <pangolin/platform.h>

#include <fstream>
#include <pangolin/image/typed_image.h>

#ifdef HAVE_OPENEXR
#include <ImfChannelList.h>
#include <ImfInputFile.h>
#include <ImfOutputFile.h>
#include <ImfIO.h>
#endif // HAVE_OPENEXR

namespace pangolin {

#ifdef HAVE_OPENEXR
Imf::PixelType OpenEXRPixelType(int channel_bits)
{
    if( channel_bits == 16 ) {
        return Imf::PixelType::HALF;
    }else if( channel_bits == 32 ) {
        return Imf::PixelType::FLOAT;
    }else{
        throw std::runtime_error("Unsupported OpenEXR Pixel Type.");
    }
}

void SetOpenEXRChannels(Imf::ChannelList& ch, const pangolin::PixelFormat& fmt)
{
    const char* CHANNEL_NAMES[] = {"R","G","B","A"};
    for(size_t c=0; c < fmt.channels; ++c) {
        ch.insert( CHANNEL_NAMES[c], Imf::Channel(OpenEXRPixelType(fmt.channel_bits[c])) );
    }
}

class StdIStream: public Imf::IStream
{
  public:
    StdIStream (std::istream &is):
        Imf::IStream ("stream"),
        _is (&is)
    {
    }

    virtual bool read (char c[/*n*/], int n)
    {
        if (!*_is)
            throw std::runtime_error("Unexpected end of file.");
        _is->read (c, n);
        if (_is->gcount() < n)
        {
            throw std::runtime_error("Early end of file");
            return false;
        }
        return true;
    }

    virtual Imf::Int64 tellg ()
    {
        return std::streamoff (_is->tellg());
    }

    virtual void seekg (Imf::Int64 pos)
    {
        _is->seekg (pos);
    }

    virtual void clear ()
    {
        _is->clear();
    }

  private:
    std::istream *	_is;
};

PixelFormat GetPixelFormat(const Imf::Header& header)
{
    const Imf::ChannelList &channels = header.channels();
    size_t count = 0;
    for (Imf::ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i){
        const Imf::Channel& channel = i.channel();
        if (channel.type != Imf::FLOAT){
            throw std::invalid_argument("Currently, only 32-bit float OpenEXR files are supported.");
        }
        count += 1;
    }

    switch (count) {
        case 1: return PixelFormatFromString("GRAY32F");
        case 3: return PixelFormatFromString("RGB96F");
        case 4: return PixelFormatFromString("RGBA128F");
        default: throw std::invalid_argument("Currently, only 1, 3 or 4-channel OpenEXR files are supported.");
    }
}

#endif //HAVE_OPENEXR

TypedImage LoadExr(std::istream& source)
{
#ifdef HAVE_OPENEXR
    StdIStream istream(source);
    Imf::InputFile file(istream);
    PANGO_ENSURE(file.isComplete());

    Imath::Box2i dw = file.header().dataWindow();
    int width = dw.max.x - dw.min.x + 1;
    int height = dw.max.y - dw.min.y + 1;

    PixelFormat format = GetPixelFormat(file.header());
    TypedImage img(width, height, format);

    char *imgBase = (char *) img.ptr - (dw.min.x + dw.min.y * width) * sizeof(float) * format.channels;
    Imf::FrameBuffer fb;

    const Imf::ChannelList &channels = file.header().channels();
    size_t c = 0;
    for (Imf::ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i){
        fb.insert(i.name(), Imf::Slice(
                        Imf::FLOAT, imgBase + sizeof(float) * c++,
                        sizeof(float) * format.channels,
                        sizeof(float) * format.channels * size_t(width),
                        1, 1,
                        0.0));
    }

    file.setFrameBuffer(fb);
    file.readPixels(dw.min.y, dw.max.y);

    return img;
#else
    PANGOLIN_UNUSED(source);
    throw std::runtime_error("Rebuild Pangolin for EXR support.");
#endif //HAVE_OPENEXR
}

void SaveExr(const Image<unsigned char>& image_in, const pangolin::PixelFormat& fmt, const std::string& filename, bool top_line_first)
{
#ifdef HAVE_OPENEXR
    ManagedImage<unsigned char> flip_image;
    Image<unsigned char> image;

    if(top_line_first) {
        image = image_in;
    }else{
        flip_image.Reinitialise(image_in.pitch,image_in.h);
        for(size_t y=0; y<image_in.h; ++y) {
            std::memcpy(flip_image.RowPtr(y), image_in.RowPtr(y), image_in.pitch);
        }
        image = flip_image;
    }

    Imf::Header header (image.w, image.h);
    SetOpenEXRChannels(header.channels(), fmt);

    Imf::OutputFile file (filename.c_str(), header);
    Imf::FrameBuffer frameBuffer;

    int ch=0;
    size_t ch_bits = 0;
    for(Imf::ChannelList::Iterator it = header.channels().begin(); it != header.channels().end(); ++it)
    {
        frameBuffer.insert(
            it.name(),
            Imf::Slice(
                it.channel().type,
                (char*)image.ptr + ch_bits/8,
                fmt.channel_bits[ch]/8,
                image.pitch
            )
        );

        ch_bits += fmt.channel_bits[ch++];
    }

    file.setFrameBuffer(frameBuffer);
    file.writePixels(image.h);

#else
    PANGOLIN_UNUSED(image_in);
    PANGOLIN_UNUSED(fmt);
    PANGOLIN_UNUSED(filename);
    PANGOLIN_UNUSED(top_line_first);
    throw std::runtime_error("EXR Support not enabled. Please rebuild Pangolin.");
#endif // HAVE_OPENEXR
}

}
<|endoftext|>


<commit_before>/* Please refer to license.txt */

#include "interface.hpp"

#include <iostream>

#include "../graphic/2d/2d.hpp"
#include "../graphic/window/window.hpp"

#include "../misc/time.hpp"

#include "../file/file.hpp"

namespace GEngine
{

namespace mui
{

Interface::Interface() : timer(mmisc::mtime::Timer::create())
{
	//timer = new mmisc::mtime::Timer;
	//d2d = nullptr;
	cegui_system = nullptr;

	cegui_configfile_path = CEGUI_CONFIGFILE_PATH;
	cegui_logfile_path = CEGUI_LOGFILE_PATH;
	cegui_schemes_path = CEGUI_SCHEMES_PATH;
	cegui_imagesets_path = CEGUI_IMAGESETS_PATH;
	cegui_fonts_path = CEGUI_FONTS_PATH;
	cegui_layouts_path = CEGUI_LAYOUTS_PATH;
	cegui_looknfeels_path = CEGUI_LOOKNFEELS_PATH;
	cegui_luascripts_path = CEGUI_LUASCRIPTS_PATH;

	cegui_resourceprovider = nullptr;
	//cegui_root_window = nullptr;
	//cegui_windowmanager = nullptr;
}

Interface::~Interface()
{
	/*if (d2d)
	{
		d2d = nullptr;
	}

	if (cegui_root_window)
	{
		delete cegui_root_window;
	}*/

	cegui_system = nullptr;
	cegui_resourceprovider = nullptr;
}

bool Interface::initialize(mgfx::d2d::D2D &d2d, std::vector<std::string> cegui_schemes)
{
	//d2d = &_d2d;
	//d2d->window->showMouseCursor(false); //CEGUI's default schemes are fugly with the mouse or don't have one at all. Using default sfml mouse. //TODO: Handle mouse.

	try
	{
		CEGUI::OpenGLRenderer& myRenderer = CEGUI::OpenGLRenderer::create();

		std::string log_directory("");
		mfile::FileManager::separatePathFromFilename(cegui_logfile_path, log_directory);
		//Check if the directory the cegui logfile is going to be kept in exists. It not, create it.
		if (!mfile::FileManager::directoryExists(log_directory))
		{
			mfile::FileManager::mkDir(log_directory);
		}

		CEGUI::System::create(myRenderer, nullptr, nullptr, nullptr, nullptr, cegui_configfile_path, cegui_logfile_path);

		//Initialise the required dirs for the CEGUI DefaultResourceProvider.
		cegui_resourceprovider = static_cast<CEGUI::DefaultResourceProvider*>(CEGUI::System::getSingleton().getResourceProvider());
		cegui_resourceprovider->setResourceGroupDirectory("imagesets", cegui_imagesets_path);
		cegui_resourceprovider->setResourceGroupDirectory("fonts", cegui_fonts_path);
		cegui_resourceprovider->setResourceGroupDirectory("layouts", cegui_layouts_path);
		cegui_resourceprovider->setResourceGroupDirectory("looknfeels", cegui_looknfeels_path);
		cegui_resourceprovider->setResourceGroupDirectory("lua_scripts", cegui_luascripts_path);
		cegui_resourceprovider->setResourceGroupDirectory("schemes", cegui_schemes_path);
		//According to the documentation, this is only really needed if you are using Xerces and need to specify the schemas location.
		//cegui_resourceprovider->setResourceGroupDirectory("schemas", "datafiles/xml_schemas/");

		//Set the default resource groups to be used
		CEGUI::ImageManager::setImagesetDefaultResourceGroup("imagesets");
		CEGUI::Font::setDefaultResourceGroup("fonts");
		CEGUI::Scheme::setDefaultResourceGroup("schemes");
		CEGUI::ScriptModule::setDefaultResourceGroup("lua_scripts");
		CEGUI::WidgetLookManager::setDefaultResourceGroup("looknfeels");
		CEGUI::WindowManager::setDefaultResourceGroup("layouts");
		//This is only needed if the resourceprovider's schemas is set.
		//Setup default group for validation schemas.
		//CEGUI::XMLParser* parser = CEGUI::System::getSingleton().getXMLParser();
		//if (parser->isPropertyPresent("SchemaDefaultResourceGroup"))
		//{
		//	parser->setProperty("SchemaDefaultResourceGroup", "schemas");
		//}

		//Load the schemes specified in cegui_schemes.
		for (std::vector<std::string>::iterator i = cegui_schemes.begin(); i != cegui_schemes.end(); ++i) //TODO: Vector iterator.
		{
			CEGUI::SchemeManager::getSingleton().createFromFile(*i + ".scheme");
			loaded_schemes.push_back(*i); //Save it so we know how to access it later, if needed.
		}

		//TODO: Handle the mouse.
		/*CEGUI::System::getSingleton().getDefaultGUIContext().getMouseCursor().setDefaultImage("GlossySerpent/MouseArrow");
		CEGUI::System::getSingleton().getDefaultGUIContext().getMouseCursor().show();*/

		//CEGUI::System::getSingleton().getDefaultGUIContext().setDefaultTooltipType("GlossySerpent/Tooltip"); //TODO: Set in XML, if possible.

		sf::Vector2i coords = sf::Mouse::getPosition(*d2d.window->window2d);
		CEGUI::System::getSingleton().getDefaultGUIContext().injectMousePosition(coords.x, coords.y);

		//Map SFML Key and Mouse stuff to CEGUI stuff for injecting input into CEGUI.
		mapSFMLKeysToCEGUI();
		mapSFMLMouseToCEGUI();

		d2d.cegui_gui_context = &CEGUI::System::getSingleton().getDefaultGUIContext(); //Point this accordingly.
		d2d.cegui_renderer = &myRenderer;
		d2d.default_d2d = true;

		timer.start();
	}
	catch(CEGUI::Exception& e)
	{
		std::cout << "CEGUI Exception:" << e.getMessage().c_str() << "\n";
		return false;
	}

	addD2D(d2d); //Add the D2D to the list of D2Ds.

	return true; //Success.
}

bool Interface::loadFont(std::string filepath)
{
	font.loadFromFile(filepath);

	return true;
}

void Interface::update()
{
	float time_elapsed = ((float)timer.millisecondsElapsed() / (float)1000);

	unhandled_events.clear(); //Empty the unhandled events vector.

	for (std::vector<mgfx::d2d::D2D* >::iterator iter = windows.begin(); iter != windows.end(); ++iter)
	{
		(*iter)->window->setActive();

		mgfx::d2d::D2D *d2d = *iter; //First point to this so I don't have to type crazy things every time.
		//mgfx::d2d::D2D *d2d = windows[i]; //First point to this so I don't have to type crazy things every time.
		CEGUI::GUIContext& context = *d2d->cegui_gui_context; //Next, point to this so that I don't have to type out the full thing every time.

		context.injectTimePulse(time_elapsed);

		//std::cout << "Context size: " << context.getSurfaceSize() << "\n";

		context.getMouseCursor().draw(); //Force draw it because it doesn't seem to want to work otherwise.

		//Now, handle injecting events into CEGUI.
		for (unsigned int i = 0; i < d2d->window->events.size(); ++i)
		{
			switch (d2d->window->events[i].type)
			{
			case sf::Event::KeyPressed:
				if (!context.injectKeyDown(sfml_cegui_keymap[d2d->window->events[i].key.code]))
				{
					addUnhandledEvent(d2d->window->events[i], *d2d->window);
				}
				break;
			case sf::Event::KeyReleased:
				if (!context.injectKeyUp(sfml_cegui_keymap[d2d->window->events[i].key.code]))
				{
					addUnhandledEvent(d2d->window->events[i], *d2d->window);
				}
				break;
			case sf::Event::TextEntered:
				if (!context.injectChar(static_cast<char>(d2d->window->events[i].text.unicode)))
				{
					addUnhandledEvent(d2d->window->events[i], *d2d->window);
				}
				break;
			case sf::Event::MouseMoved:
				{
					sf::Vector2i coords = sf::Mouse::getPosition(*d2d->window->window2d);
					context.injectMousePosition(coords.x, coords.y);
				}
				break;
			case sf::Event::MouseButtonPressed:
				if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
				{
					if(!context.injectMouseButtonDown(CEGUI::LeftButton))
					{
						addUnhandledEvent(d2d->window->events[i], *d2d->window);
						std::cout << "UNHANDLED MOUSE BUTTON LEFT PRESSED EVENT BUAHAHAHAHA!";
					}
				}
				else if (sf::Mouse::isButtonPressed(sf::Mouse::Middle))
				{
					if(!context.injectMouseButtonDown(CEGUI::MiddleButton))
					{
						addUnhandledEvent(d2d->window->events[i], *d2d->window);
					}
				}
				else if (sf::Mouse::isButtonPressed(sf::Mouse::Right))
				{
					if(!context.injectMouseButtonDown(CEGUI::RightButton))
					{
						addUnhandledEvent(d2d->window->events[i], *d2d->window);
					}
				}
				break;
			case sf::Event::MouseButtonReleased:
				switch (d2d->window->events[i].mouseButton.button)
				{
				case sf::Mouse::Left:
					if(!context.injectMouseButtonUp(CEGUI::LeftButton))
					{
						addUnhandledEvent(d2d->window->events[i], *d2d->window);
					}
					break;
				case sf::Mouse::Middle:
					if(!context.injectMouseButtonUp(CEGUI::MiddleButton))
					{
						addUnhandledEvent(d2d->window->events[i], *d2d->window);
					}
					break;
				case sf::Mouse::Right:
					if(!context.injectMouseButtonUp(CEGUI::RightButton))
					{
						addUnhandledEvent(d2d->window->events[i], *d2d->window);
					}
					break;
				}
				break;
			case sf::Event::MouseWheelMoved:
				if(!context.injectMouseWheelChange(d2d->window->events[i].mouseWheel.delta))
				{
					addUnhandledEvent(d2d->window->events[i], *d2d->window);
				}
				break;
			default:
				break;
			}
		}

		/*glBegin(GL_TRIANGLES);
			glVertex3f(  0.0f,  1.0f, 0.0f );
			glVertex3f( -1.0f, -1.0f, 0.0f );
			glVertex3f(  1.0f, -1.0f, 0.0f );
		glEnd( );*/

		//TODO: gui context draw() ?
		d2d->cegui_renderer->beginRendering();
		context.draw();
		d2d->cegui_renderer->endRendering();
	}

	//CEGUI::System::getSingleton().renderAllGUIContexts(); //Render all of CEGUI's stuffs.
	//TODO: Maybe the problem is the resource browser window doesn't have a root window set? Hmm...
	//I need to:
	//	* Post on the forums asking about how to render one context at a time.
	//	* And/or post on the forums asking about how to render to multiple SFML windows.

	CEGUI::System::getSingleton().injectTimePulse(time_elapsed);
}

CEGUI::Window* Interface::getRootWindow(mgfx::d2d::D2D &d2d)
{
	//return cegui_root_window;
	return d2d.getRootWindow();
}

void Interface::setRootWindow(CEGUI::Window *window, mgfx::d2d::D2D &d2d) //Sets the root window.
{
	/*cegui_root_window = window;
	CEGUI::System::getSingleton().getDefaultGUIContext().setRootWindow(cegui_root_window);*/
	d2d.cegui_root_window = window;
	d2d.cegui_gui_context->setRootWindow(d2d.cegui_root_window);
}

CEGUI::Window* Interface::createVirtualWindowFromLayout(std::string layout/*, bool root*/)
{
	CEGUI::Window *window = CEGUI::WindowManager::getSingleton().loadLayoutFromFile(layout);
	/*if (root) //If it's supposed to be the root window...
	{
		setRootWindow(window); //Set it.
	}*/

	return window;
}

void Interface::addD2D(mgfx::d2d::D2D &d2d)
{
	//TODO: gui context setRenderTarget (RenderTarget &target) ?
	d2d.window->setActive();
	if (!d2d.cegui_renderer)
	{
		//When creating a renderer, perhaps force SFML to set the viewport to the d2d's window?
		d2d.cegui_renderer = &CEGUI::OpenGLRenderer::create();
	}

	if (!d2d.cegui_gui_context)
	{
		d2d.cegui_gui_context = &CEGUI::System::getSingleton().createGUIContext(d2d.cegui_renderer->getDefaultRenderTarget());
	}

	windows.push_back(&d2d);
}

void Interface::addUnhandledEvent(sf::Event& event, mgfx::Window& window)
{
	unhandledEvent unhandled_event(window, event);
	unhandled_events.push_back(unhandled_event);
}

} //namespace mui

} //namespace GEngine
<commit_msg>Testing something else out.<commit_after>/* Please refer to license.txt */

#include "interface.hpp"

#include <iostream>

#include "../graphic/2d/2d.hpp"
#include "../graphic/window/window.hpp"

#include "../misc/time.hpp"

#include "../file/file.hpp"

namespace GEngine
{

namespace mui
{

Interface::Interface() : timer(mmisc::mtime::Timer::create())
{
	//timer = new mmisc::mtime::Timer;
	//d2d = nullptr;
	cegui_system = nullptr;

	cegui_configfile_path = CEGUI_CONFIGFILE_PATH;
	cegui_logfile_path = CEGUI_LOGFILE_PATH;
	cegui_schemes_path = CEGUI_SCHEMES_PATH;
	cegui_imagesets_path = CEGUI_IMAGESETS_PATH;
	cegui_fonts_path = CEGUI_FONTS_PATH;
	cegui_layouts_path = CEGUI_LAYOUTS_PATH;
	cegui_looknfeels_path = CEGUI_LOOKNFEELS_PATH;
	cegui_luascripts_path = CEGUI_LUASCRIPTS_PATH;

	cegui_resourceprovider = nullptr;
	//cegui_root_window = nullptr;
	//cegui_windowmanager = nullptr;
}

Interface::~Interface()
{
	/*if (d2d)
	{
		d2d = nullptr;
	}

	if (cegui_root_window)
	{
		delete cegui_root_window;
	}*/

	cegui_system = nullptr;
	cegui_resourceprovider = nullptr;
}

bool Interface::initialize(mgfx::d2d::D2D &d2d, std::vector<std::string> cegui_schemes)
{
	//d2d = &_d2d;
	//d2d->window->showMouseCursor(false); //CEGUI's default schemes are fugly with the mouse or don't have one at all. Using default sfml mouse. //TODO: Handle mouse.

	try
	{
		CEGUI::OpenGLRenderer& myRenderer = CEGUI::OpenGLRenderer::create();

		std::string log_directory("");
		mfile::FileManager::separatePathFromFilename(cegui_logfile_path, log_directory);
		//Check if the directory the cegui logfile is going to be kept in exists. It not, create it.
		if (!mfile::FileManager::directoryExists(log_directory))
		{
			mfile::FileManager::mkDir(log_directory);
		}

		CEGUI::System::create(myRenderer, nullptr, nullptr, nullptr, nullptr, cegui_configfile_path, cegui_logfile_path);

		//Initialise the required dirs for the CEGUI DefaultResourceProvider.
		cegui_resourceprovider = static_cast<CEGUI::DefaultResourceProvider*>(CEGUI::System::getSingleton().getResourceProvider());
		cegui_resourceprovider->setResourceGroupDirectory("imagesets", cegui_imagesets_path);
		cegui_resourceprovider->setResourceGroupDirectory("fonts", cegui_fonts_path);
		cegui_resourceprovider->setResourceGroupDirectory("layouts", cegui_layouts_path);
		cegui_resourceprovider->setResourceGroupDirectory("looknfeels", cegui_looknfeels_path);
		cegui_resourceprovider->setResourceGroupDirectory("lua_scripts", cegui_luascripts_path);
		cegui_resourceprovider->setResourceGroupDirectory("schemes", cegui_schemes_path);
		//According to the documentation, this is only really needed if you are using Xerces and need to specify the schemas location.
		//cegui_resourceprovider->setResourceGroupDirectory("schemas", "datafiles/xml_schemas/");

		//Set the default resource groups to be used
		CEGUI::ImageManager::setImagesetDefaultResourceGroup("imagesets");
		CEGUI::Font::setDefaultResourceGroup("fonts");
		CEGUI::Scheme::setDefaultResourceGroup("schemes");
		CEGUI::ScriptModule::setDefaultResourceGroup("lua_scripts");
		CEGUI::WidgetLookManager::setDefaultResourceGroup("looknfeels");
		CEGUI::WindowManager::setDefaultResourceGroup("layouts");
		//This is only needed if the resourceprovider's schemas is set.
		//Setup default group for validation schemas.
		//CEGUI::XMLParser* parser = CEGUI::System::getSingleton().getXMLParser();
		//if (parser->isPropertyPresent("SchemaDefaultResourceGroup"))
		//{
		//	parser->setProperty("SchemaDefaultResourceGroup", "schemas");
		//}

		//Load the schemes specified in cegui_schemes.
		for (std::vector<std::string>::iterator i = cegui_schemes.begin(); i != cegui_schemes.end(); ++i) //TODO: Vector iterator.
		{
			CEGUI::SchemeManager::getSingleton().createFromFile(*i + ".scheme");
			loaded_schemes.push_back(*i); //Save it so we know how to access it later, if needed.
		}

		//TODO: Handle the mouse.
		/*CEGUI::System::getSingleton().getDefaultGUIContext().getMouseCursor().setDefaultImage("GlossySerpent/MouseArrow");
		CEGUI::System::getSingleton().getDefaultGUIContext().getMouseCursor().show();*/

		//CEGUI::System::getSingleton().getDefaultGUIContext().setDefaultTooltipType("GlossySerpent/Tooltip"); //TODO: Set in XML, if possible.

		sf::Vector2i coords = sf::Mouse::getPosition(*d2d.window->window2d);
		CEGUI::System::getSingleton().getDefaultGUIContext().injectMousePosition(coords.x, coords.y);

		//Map SFML Key and Mouse stuff to CEGUI stuff for injecting input into CEGUI.
		mapSFMLKeysToCEGUI();
		mapSFMLMouseToCEGUI();

		d2d.cegui_gui_context = &CEGUI::System::getSingleton().getDefaultGUIContext(); //Point this accordingly.
		d2d.cegui_renderer = &myRenderer;
		d2d.default_d2d = true;

		timer.start();
	}
	catch(CEGUI::Exception& e)
	{
		std::cout << "CEGUI Exception:" << e.getMessage().c_str() << "\n";
		return false;
	}

	addD2D(d2d); //Add the D2D to the list of D2Ds.

	return true; //Success.
}

bool Interface::loadFont(std::string filepath)
{
	font.loadFromFile(filepath);

	return true;
}

void Interface::update()
{
	float time_elapsed = ((float)timer.millisecondsElapsed() / (float)1000);

	unhandled_events.clear(); //Empty the unhandled events vector.

	for (std::vector<mgfx::d2d::D2D* >::iterator iter = windows.begin(); iter != windows.end(); ++iter)
	{
		(*iter)->window->setActive();

		mgfx::d2d::D2D *d2d = *iter; //First point to this so I don't have to type crazy things every time.
		//mgfx::d2d::D2D *d2d = windows[i]; //First point to this so I don't have to type crazy things every time.
		CEGUI::GUIContext& context = *d2d->cegui_gui_context; //Next, point to this so that I don't have to type out the full thing every time.

		context.injectTimePulse(time_elapsed);

		//std::cout << "Context size: " << context.getSurfaceSize() << "\n";

		context.getMouseCursor().draw(); //Force draw it because it doesn't seem to want to work otherwise.

		//Now, handle injecting events into CEGUI.
		for (unsigned int i = 0; i < d2d->window->events.size(); ++i)
		{
			switch (d2d->window->events[i].type)
			{
			case sf::Event::KeyPressed:
				if (!context.injectKeyDown(sfml_cegui_keymap[d2d->window->events[i].key.code]))
				{
					addUnhandledEvent(d2d->window->events[i], *d2d->window);
				}
				break;
			case sf::Event::KeyReleased:
				if (!context.injectKeyUp(sfml_cegui_keymap[d2d->window->events[i].key.code]))
				{
					addUnhandledEvent(d2d->window->events[i], *d2d->window);
				}
				break;
			case sf::Event::TextEntered:
				if (!context.injectChar(static_cast<char>(d2d->window->events[i].text.unicode)))
				{
					addUnhandledEvent(d2d->window->events[i], *d2d->window);
				}
				break;
			case sf::Event::MouseMoved:
				{
					sf::Vector2i coords = sf::Mouse::getPosition(*d2d->window->window2d);
					context.injectMousePosition(coords.x, coords.y);
				}
				break;
			case sf::Event::MouseButtonPressed:
				if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
				{
					if(context.injectMouseButtonDown(CEGUI::LeftButton))
					{
						addUnhandledEvent(d2d->window->events[i], *d2d->window);
						std::cout << "UNHANDLED MOUSE BUTTON LEFT PRESSED EVENT BUAHAHAHAHA!";
					}
				}
				else if (sf::Mouse::isButtonPressed(sf::Mouse::Middle))
				{
					if(!context.injectMouseButtonDown(CEGUI::MiddleButton))
					{
						addUnhandledEvent(d2d->window->events[i], *d2d->window);
					}
				}
				else if (sf::Mouse::isButtonPressed(sf::Mouse::Right))
				{
					if(!context.injectMouseButtonDown(CEGUI::RightButton))
					{
						addUnhandledEvent(d2d->window->events[i], *d2d->window);
					}
				}
				break;
			case sf::Event::MouseButtonReleased:
				switch (d2d->window->events[i].mouseButton.button)
				{
				case sf::Mouse::Left:
					if(!context.injectMouseButtonUp(CEGUI::LeftButton))
					{
						addUnhandledEvent(d2d->window->events[i], *d2d->window);
					}
					break;
				case sf::Mouse::Middle:
					if(!context.injectMouseButtonUp(CEGUI::MiddleButton))
					{
						addUnhandledEvent(d2d->window->events[i], *d2d->window);
					}
					break;
				case sf::Mouse::Right:
					if(!context.injectMouseButtonUp(CEGUI::RightButton))
					{
						addUnhandledEvent(d2d->window->events[i], *d2d->window);
					}
					break;
				}
				break;
			case sf::Event::MouseWheelMoved:
				if(!context.injectMouseWheelChange(d2d->window->events[i].mouseWheel.delta))
				{
					addUnhandledEvent(d2d->window->events[i], *d2d->window);
				}
				break;
			default:
				break;
			}
		}

		/*glBegin(GL_TRIANGLES);
			glVertex3f(  0.0f,  1.0f, 0.0f );
			glVertex3f( -1.0f, -1.0f, 0.0f );
			glVertex3f(  1.0f, -1.0f, 0.0f );
		glEnd( );*/

		//TODO: gui context draw() ?
		d2d->cegui_renderer->beginRendering();
		context.draw();
		d2d->cegui_renderer->endRendering();
	}

	//CEGUI::System::getSingleton().renderAllGUIContexts(); //Render all of CEGUI's stuffs.
	//TODO: Maybe the problem is the resource browser window doesn't have a root window set? Hmm...
	//I need to:
	//	* Post on the forums asking about how to render one context at a time.
	//	* And/or post on the forums asking about how to render to multiple SFML windows.

	CEGUI::System::getSingleton().injectTimePulse(time_elapsed);
}

CEGUI::Window* Interface::getRootWindow(mgfx::d2d::D2D &d2d)
{
	//return cegui_root_window;
	return d2d.getRootWindow();
}

void Interface::setRootWindow(CEGUI::Window *window, mgfx::d2d::D2D &d2d) //Sets the root window.
{
	/*cegui_root_window = window;
	CEGUI::System::getSingleton().getDefaultGUIContext().setRootWindow(cegui_root_window);*/
	d2d.cegui_root_window = window;
	d2d.cegui_gui_context->setRootWindow(d2d.cegui_root_window);
}

CEGUI::Window* Interface::createVirtualWindowFromLayout(std::string layout/*, bool root*/)
{
	CEGUI::Window *window = CEGUI::WindowManager::getSingleton().loadLayoutFromFile(layout);
	/*if (root) //If it's supposed to be the root window...
	{
		setRootWindow(window); //Set it.
	}*/

	return window;
}

void Interface::addD2D(mgfx::d2d::D2D &d2d)
{
	//TODO: gui context setRenderTarget (RenderTarget &target) ?
	d2d.window->setActive();
	if (!d2d.cegui_renderer)
	{
		//When creating a renderer, perhaps force SFML to set the viewport to the d2d's window?
		d2d.cegui_renderer = &CEGUI::OpenGLRenderer::create();
	}

	if (!d2d.cegui_gui_context)
	{
		d2d.cegui_gui_context = &CEGUI::System::getSingleton().createGUIContext(d2d.cegui_renderer->getDefaultRenderTarget());
	}

	windows.push_back(&d2d);
}

void Interface::addUnhandledEvent(sf::Event& event, mgfx::Window& window)
{
	unhandledEvent unhandled_event(window, event);
	unhandled_events.push_back(unhandled_event);
}

} //namespace mui

} //namespace GEngine
<|endoftext|>


<commit_before>/*
 * ClusteringCoefficient.cpp
 *
 *  Created on: 08.04.2013
 *      Author: Lukas Barth, David Weiss
 */

#include <unordered_set>

#include "ClusteringCoefficient.h"
#include "../auxiliary/Random.h"
#include "../auxiliary/Log.h"
#include <omp.h>

namespace NetworKit {

std::vector<double> ClusteringCoefficient::exactLocal(Graph &G) {
	count z = G.upperNodeIdBound();
	std::vector<double> coefficient(z); // $c(u) := \frac{2 \cdot |E(N(u))| }{\deg(u) \cdot ( \deg(u) - 1)}$

	std::vector<std::vector<bool> > nodeMarker(omp_get_max_threads());

	for (auto & nm : nodeMarker) {
		nm.resize(z, false);
	}

	G.balancedParallelForNodes([&](node u) {
		count d = G.degree(u);

		if (d < 2) {
			coefficient[u] = 0.0;
		} else {
			size_t tid = omp_get_thread_num();
			count triangles = 0;

			G.forEdgesOf(u, [&](node u, node v) {
				nodeMarker[tid][v] = true;
			});

			G.forEdgesOf(u, [&](node u, node v) {
				G.forEdgesOf(v, [&](node v, node w) {
					if (nodeMarker[tid][w]) {
						triangles += 1;
					}
				});
			});

			G.forEdgesOf(u, [&](node u, node v) {
				nodeMarker[tid][v] = false;
			});

			coefficient[u] = (double) triangles / (double)(d * (d - 1)); // No division by 2 since triangles are counted twice as well!
		}
	});

	return coefficient;
}

double ClusteringCoefficient::avgLocal(Graph& G) {

	auto coefficients = exactLocal(G); // $c(u) := \frac{2 \cdot |E(N(u))| }{\deg(u) \cdot ( \deg(u) - 1)}$

	double sum = 0.0;

	G.forNodes([&](node u) {
		sum += coefficients[u];
	});

	return sum / (double) G.numberOfNodes();
}

double ClusteringCoefficient::approxAvgLocal(Graph& G, const count trials) {

	double triangles = 0;
	for (count k = 0; k < trials; ++k) {
		node v = G.randomNode();
		TRACE("trial ", k, " sampled node ", v);

		if (G.degree(v) < 2) {
			// this vertex can never be part of a triangle,
			// (nor middle point of a path of length 3)
			continue;
		}

		TRACE("deg(v) = ", G.degree(v));
		node u = G.randomNeighbor(v);
		node w = G.randomNeighbor(v);
		TRACE("u=", u);
		TRACE("w=", w);

		// TODO This could be sped up for degree(v) == 2...
		while (u == w) {
			w = G.randomNeighbor(v);
			TRACE("w=", w);
		}

		if (G.hasEdge(u,w)) {
			triangles++;
		}
	}

	return triangles / (double) trials;
}

double ClusteringCoefficient::exactGlobal(Graph& G) {
	count z = G.upperNodeIdBound();
	std::vector<count> triangles(z); // triangles including node u (every triangle is counted six times)

	std::vector<std::vector<bool> > nodeMarker(omp_get_max_threads());
	for (auto &nm : nodeMarker) {
		nm.resize(z, false);
	}

	G.balancedParallelForNodes([&](node u){

		size_t tid = omp_get_thread_num();
		count tr = 0;

		if (G.degree(u) > 1) {
			G.forEdgesOf(u, [&](node u, node v) {
				nodeMarker[tid][v] = true;
			});

			G.forEdgesOf(u, [&](node u, node v) {
				G.forEdgesOf(v, [&](node v, node w) {
					if (nodeMarker[tid][w]) {
						tr += 1;
					}
				});
			});

			G.forEdgesOf(u, [&](node u, node v) {
				nodeMarker[tid][v] = false;
			});
		}

		triangles[u] = tr;
	});

  double denominator = G.parallelSumForNodes([&](node u){
		return G.degree(u) * (G.degree(u) - 1);
	});

	double cc = G.parallelSumForNodes([&](node u){
		return triangles[u];
	});

	cc /= denominator;

	return cc;
}

double ClusteringCoefficient::approxGlobal(Graph& G, const count trials) {
	count z = G.upperNodeIdBound();

  // Calculate prefix sum over the nodes where each node v counts deg(v)*(deg(v)-1) times
	std::vector<count> weight(z);
	count psum = 0;
	G.forNodes([&](node v) {
		psum += G.degree(v) * (G.degree(v) - 1);
		weight[v] = psum;
	});

	// WARNING: I assume RAND_MAX to be larger than PSUM. If this should not hold for an application
	// or implementation of the standard library, a more sophisticated version of determining a
	// vertex uniformly at random must be used.

	double triangles = 0;
	for (count k = 0; k < trials; ++k) {
		count r = Aux::Random::integer(psum - 1);

		// plain old binary search:
		index low = 0;
		index high = G.upperNodeIdBound();
		while (low < high) {
			index middle = (low + high) / 2;

			if (weight[middle] < r) {
				low = middle + 1;
			} else if (weight[middle] > r) {
				high = middle;
			} else {
				low = high = middle;
			}
		}

		node v = low; // ewww.. setting a vertex to an index.. but works.

		count vDeg = G.degree(v);
		if (vDeg < 2) {
			// this vertex can never be part of a triangle,
			// nor middle point of a path of length 3
			--k; // do not count trial
			continue;
		}

		node u = G.randomNeighbor(v);
		node w = G.randomNeighbor(v);

		// TODO This could be sped up for degree(v) == 2...
		while (u == w) {
			w = G.randomNeighbor(v);
		}

		if (G.hasEdge(u,w)) {
			triangles++;
		}
	}

	return triangles / trials;
}

} /* namespace NetworKit */
<commit_msg>Revert "ClusteringCoefficient: Adapt approximation to changed exact measure"<commit_after>/*
 * ClusteringCoefficient.cpp
 *
 *  Created on: 08.04.2013
 *      Author: Lukas Barth, David Weiss
 */

#include <unordered_set>

#include "ClusteringCoefficient.h"
#include "../auxiliary/Random.h"
#include "../auxiliary/Log.h"
#include <omp.h>

namespace NetworKit {

std::vector<double> ClusteringCoefficient::exactLocal(Graph &G) {
	count z = G.upperNodeIdBound();
	std::vector<double> coefficient(z); // $c(u) := \frac{2 \cdot |E(N(u))| }{\deg(u) \cdot ( \deg(u) - 1)}$

	std::vector<std::vector<bool> > nodeMarker(omp_get_max_threads());

	for (auto & nm : nodeMarker) {
		nm.resize(z, false);
	}

	G.balancedParallelForNodes([&](node u) {
		count d = G.degree(u);

		if (d < 2) {
			coefficient[u] = 0.0;
		} else {
			size_t tid = omp_get_thread_num();
			count triangles = 0;

			G.forEdgesOf(u, [&](node u, node v) {
				nodeMarker[tid][v] = true;
			});

			G.forEdgesOf(u, [&](node u, node v) {
				G.forEdgesOf(v, [&](node v, node w) {
					if (nodeMarker[tid][w]) {
						triangles += 1;
					}
				});
			});

			G.forEdgesOf(u, [&](node u, node v) {
				nodeMarker[tid][v] = false;
			});

			coefficient[u] = (double) triangles / (double)(d * (d - 1)); // No division by 2 since triangles are counted twice as well!
		}
	});

	return coefficient;
}

double ClusteringCoefficient::avgLocal(Graph& G) {

	auto coefficients = exactLocal(G); // $c(u) := \frac{2 \cdot |E(N(u))| }{\deg(u) \cdot ( \deg(u) - 1)}$

	double sum = 0.0;

	G.forNodes([&](node u) {
		sum += coefficients[u];
	});

	return sum / (double) G.numberOfNodes();
}

double ClusteringCoefficient::approxAvgLocal(Graph& G, const count trials) {

	double triangles = 0;
	for (count k = 0; k < trials; ++k) {
		node v = G.randomNode();
		TRACE("trial ", k, " sampled node ", v);

		if (G.degree(v) < 2) {
			// this vertex can never be part of a triangle,
			// nor middle point of a path of length 3
			--k;  // do not count trial
			continue;
		}

		TRACE("deg(v) = ", G.degree(v));
		node u = G.randomNeighbor(v);
		node w = G.randomNeighbor(v);
		TRACE("u=", u);
		TRACE("w=", w);

		// TODO This could be sped up for degree(v) == 2...
		while (u == w) {
			w = G.randomNeighbor(v);
			TRACE("w=", w);
		}

		if (G.hasEdge(u,w)) {
			triangles++;
		}
	}

	return triangles / (double) trials;
}

double ClusteringCoefficient::exactGlobal(Graph& G) {
	count z = G.upperNodeIdBound();
	std::vector<count> triangles(z); // triangles including node u (every triangle is counted six times)

	std::vector<std::vector<bool> > nodeMarker(omp_get_max_threads());
	for (auto &nm : nodeMarker) {
		nm.resize(z, false);
	}

	G.balancedParallelForNodes([&](node u){

		size_t tid = omp_get_thread_num();
		count tr = 0;

		if (G.degree(u) > 1) {
			G.forEdgesOf(u, [&](node u, node v) {
				nodeMarker[tid][v] = true;
			});

			G.forEdgesOf(u, [&](node u, node v) {
				G.forEdgesOf(v, [&](node v, node w) {
					if (nodeMarker[tid][w]) {
						tr += 1;
					}
				});
			});

			G.forEdgesOf(u, [&](node u, node v) {
				nodeMarker[tid][v] = false;
			});
		}

		triangles[u] = tr;
	});

  double denominator = G.parallelSumForNodes([&](node u){
		return G.degree(u) * (G.degree(u) - 1);
	});

	double cc = G.parallelSumForNodes([&](node u){
		return triangles[u];
	});

	cc /= denominator;

	return cc;
}

double ClusteringCoefficient::approxGlobal(Graph& G, const count trials) {
	count z = G.upperNodeIdBound();

  // Calculate prefix sum over the nodes where each node v counts deg(v)*(deg(v)-1) times
	std::vector<count> weight(z);
	count psum = 0;
	G.forNodes([&](node v) {
		psum += G.degree(v) * (G.degree(v) - 1);
		weight[v] = psum;
	});

	// WARNING: I assume RAND_MAX to be larger than PSUM. If this should not hold for an application
	// or implementation of the standard library, a more sophisticated version of determining a
	// vertex uniformly at random must be used.

	double triangles = 0;
	for (count k = 0; k < trials; ++k) {
		count r = Aux::Random::integer(psum - 1);

		// plain old binary search:
		index low = 0;
		index high = G.upperNodeIdBound();
		while (low < high) {
			index middle = (low + high) / 2;

			if (weight[middle] < r) {
				low = middle + 1;
			} else if (weight[middle] > r) {
				high = middle;
			} else {
				low = high = middle;
			}
		}

		node v = low; // ewww.. setting a vertex to an index.. but works.

		count vDeg = G.degree(v);
		if (vDeg < 2) {
			// this vertex can never be part of a triangle,
			// nor middle point of a path of length 3
			--k; // do not count trial
			continue;
		}

		node u = G.randomNeighbor(v);
		node w = G.randomNeighbor(v);

		// TODO This could be sped up for degree(v) == 2...
		while (u == w) {
			w = G.randomNeighbor(v);
		}

		if (G.hasEdge(u,w)) {
			triangles++;
		}
	}

	return triangles / trials;
}

} /* namespace NetworKit */
<|endoftext|>


<commit_before>/*
   messengercoreprotocol.cpp - Messenger core protocol for Papillon

   Copyright (c) 2006 by Michaël Larouche <larouche@kde.org>

   Based on code copyright (c) 2004 SuSE Linux AG <http://www.suse.com>
   Based on Iris, Copyright (C) 2003  Justin Karneges

   *************************************************************************
   *                                                                       *
   * This library 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.      *
   *                                                                       *
   *************************************************************************
*/
#include "Papillon/MessengerCoreProtocol"

// Qt includes
#include <QtDebug>
#include <QtCore/QDataStream>
#include <QtCore/QTextStream>
#include <QtCore/QLatin1String>
#include <QtCore/QStringList>

// Papillon includes
#include "Papillon/NetworkMessage"

namespace Papillon
{

class MessengerCoreProtocol::Private
{
public:
	Private()
		: inNetworkMessage(0), state(MessengerCoreProtocol::NoData)
	{}

	~Private()
	{
		delete inNetworkMessage;
	}

	// buffer containing unprocessed bytes we received
	QByteArray in;
	// the transfer that is being received
	NetworkMessage *inNetworkMessage;
	// represents the protocol's overall state
	int state;
	// Represend the length of payload data to read.
	int payloadLength;
};

MessengerCoreProtocol::MessengerCoreProtocol() : QObject(), d(new Private)
{}

MessengerCoreProtocol::~MessengerCoreProtocol()
{
	qDebug() << Q_FUNC_INFO;
	delete d;
}

int MessengerCoreProtocol::state()
{
	return d->state;
}

void MessengerCoreProtocol::addIncomingData(const QByteArray &incomingBytes )
{
	// Append incoming bytes to incoming buffer
	d->in += incomingBytes;

	// convert every event in the chunk to a NetworkMessage, signalling it back to the ClientStream
	int parsedBytes = 0;
	int transferCount = 0;
	// while there is data left in the input buffer, and we are able to parse something out of it
	while ( d->in.size() && ( parsedBytes = rawToNetworkMessage( d->in ) ) )
	{
		transferCount++;
		int size =  d->in.size();
		if ( parsedBytes < size )
		{
			// Remove the parsed bytes and keep the old ones.
			d->in = d->in.right( size - parsedBytes );
		}
		else
		{
			d->in.clear();
		}
	}
}

NetworkMessage *MessengerCoreProtocol::incomingNetworkMessage()
{
	if ( d->state == Available )
	{
		d->state = NoData;
		return d->inNetworkMessage;
	}
	else
	{
		return 0;
	}
}

void MessengerCoreProtocol::outgoingNetworkMessage(NetworkMessage *outgoing)
{
	emit outgoingData( outgoing->toRawCommand() );
	// Clear the transfer.
	delete outgoing;
}

int MessengerCoreProtocol::rawToNetworkMessage(const QByteArray &raw)
{
	uint bytesParsed = 0;

	if ( raw.size() < 4 )
	{
		d->state = NeedMore;
		return bytesParsed;
	}

	QByteArray tempRaw = raw;
	QDataStream din( &tempRaw, QIODevice::ReadOnly );

	// look at first four bytes and decide what to do with the chunk
	if ( okToProceed( din ) )
	{
		if(d->state != WaitForPayload && d->state != NeedMore)
		{
			QTextStream lineStream(tempRaw);

			QString parsedLine = lineStream.readLine();

			QStringList commandList = parsedLine.split(" ");

			QString command;
			QStringList arguments;

			NetworkMessage::NetworkMessageType transferType;
			bool dummy, isNumber;
			int trId = 0, payloadLength = 0;

			command = commandList.at(0);

			// Determine the transfer type.
			if(isPayloadCommand(command))
			{
				transferType |= NetworkMessage::PayloadMessage;
				// Remove the last parameter from the command list and set the payload length.
				// So it will not be in the arguments.
				payloadLength = commandList.takeLast().toUInt(&dummy);
				qDebug() << Q_FUNC_INFO << "Begin Payload transfer, length:" << payloadLength;
			}

			// Check for a transaction ID.
			// Do not check for a transaction if the commandList size is lower than 2.
			if( commandList.size() >= 2 )
			{
				trId = commandList[1].toUInt(&isNumber);
				if(isNumber)
					transferType |= NetworkMessage::TransactionMessage;
			}

			// Begin at the third command arguments if we have a transaction ID.
			int beginAt = isNumber ? 2 : 1;
			// Fill the arguments.
			for(int i = beginAt; i < commandList.size(); ++i)
			{
				arguments << commandList[i];
			}

			NetworkMessage *receivedNetworkMessage = new NetworkMessage(transferType);
			receivedNetworkMessage->setCommand(command);
			receivedNetworkMessage->setArguments(arguments);

			if(isNumber)
				receivedNetworkMessage->setTransactionId( QString::number(trId) );

			d->inNetworkMessage = receivedNetworkMessage;

			if(payloadLength > 0)
			{
				d->payloadLength = payloadLength;
				d->state = WaitForPayload;
			}
			else
			{
				// Show parsed line here for non-payload messages.
				qDebug() << Q_FUNC_INFO << parsedLine;
				d->state = Available;
				emit incomingData();
			}

			bytesParsed = parsedLine.size() + 2; // 2 is to add \r\n to the size which was trimmed.
		}
		else if(d->state == WaitForPayload || d->state == NeedMore)
		{
			if(raw.size() < d->payloadLength)
			{
				qDebug() << Q_FUNC_INFO << "Raw size:" << raw.size() << "Payload length:" << d->payloadLength;
				d->state = NeedMore;
				return bytesParsed;
			}

			// Retrieve the full payload data from raw data (do a shared copy)
			QByteArray payloadData = raw.left(d->payloadLength);

			d->inNetworkMessage->setPayloadData(payloadData);
			qDebug() << Q_FUNC_INFO << "Byte data length:" << payloadData.size();
// 			qDebug() << Q_FUNC_INFO << "Payload data read(from CoreProtocol):" << raw;
			// Show full payload command to output
			qDebug() << Q_FUNC_INFO << d->inNetworkMessage->toRawCommand();
			d->state = Available;

			bytesParsed = payloadData.size();

			emit incomingData();
		}
	}
	return bytesParsed;
}

void MessengerCoreProtocol::reset()
{
	d->in.clear();
}

bool MessengerCoreProtocol::okToProceed(const QDataStream &din)
{
	if( din.atEnd() )
	{
		d->state = NeedMore;
		return false;
	}
	else
		return true;
}

bool MessengerCoreProtocol::isPayloadCommand(const QString &command)
{
	if( command == QLatin1String("ADL") ||
	    command == QLatin1String("GCF") ||
	    command == QLatin1String("MSG") ||
	    command == QLatin1String("QRY") ||
	    command == QLatin1String("RML") ||
	    command == QLatin1String("UBX") ||
	    command == QLatin1String("UBN") ||
	    command == QLatin1String("UUN") ||
	    command == QLatin1String("UUX")
	  )
		return true;
	else
		return false;
}

}

#include "messengercoreprotocol.moc"
//kate: indent-mode csands; tab-width 4;
<commit_msg>Initialise variable. I hope this is correct. Fixes CID 4049<commit_after>/*
   messengercoreprotocol.cpp - Messenger core protocol for Papillon

   Copyright (c) 2006 by Michaël Larouche <larouche@kde.org>

   Based on code copyright (c) 2004 SuSE Linux AG <http://www.suse.com>
   Based on Iris, Copyright (C) 2003  Justin Karneges

   *************************************************************************
   *                                                                       *
   * This library 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.      *
   *                                                                       *
   *************************************************************************
*/
#include "Papillon/MessengerCoreProtocol"

// Qt includes
#include <QtDebug>
#include <QtCore/QDataStream>
#include <QtCore/QTextStream>
#include <QtCore/QLatin1String>
#include <QtCore/QStringList>

// Papillon includes
#include "Papillon/NetworkMessage"

namespace Papillon
{

class MessengerCoreProtocol::Private
{
public:
	Private()
		: inNetworkMessage(0), state(MessengerCoreProtocol::NoData)
	{}

	~Private()
	{
		delete inNetworkMessage;
	}

	// buffer containing unprocessed bytes we received
	QByteArray in;
	// the transfer that is being received
	NetworkMessage *inNetworkMessage;
	// represents the protocol's overall state
	int state;
	// Represend the length of payload data to read.
	int payloadLength;
};

MessengerCoreProtocol::MessengerCoreProtocol() : QObject(), d(new Private)
{}

MessengerCoreProtocol::~MessengerCoreProtocol()
{
	qDebug() << Q_FUNC_INFO;
	delete d;
}

int MessengerCoreProtocol::state()
{
	return d->state;
}

void MessengerCoreProtocol::addIncomingData(const QByteArray &incomingBytes )
{
	// Append incoming bytes to incoming buffer
	d->in += incomingBytes;

	// convert every event in the chunk to a NetworkMessage, signalling it back to the ClientStream
	int parsedBytes = 0;
	int transferCount = 0;
	// while there is data left in the input buffer, and we are able to parse something out of it
	while ( d->in.size() && ( parsedBytes = rawToNetworkMessage( d->in ) ) )
	{
		transferCount++;
		int size =  d->in.size();
		if ( parsedBytes < size )
		{
			// Remove the parsed bytes and keep the old ones.
			d->in = d->in.right( size - parsedBytes );
		}
		else
		{
			d->in.clear();
		}
	}
}

NetworkMessage *MessengerCoreProtocol::incomingNetworkMessage()
{
	if ( d->state == Available )
	{
		d->state = NoData;
		return d->inNetworkMessage;
	}
	else
	{
		return 0;
	}
}

void MessengerCoreProtocol::outgoingNetworkMessage(NetworkMessage *outgoing)
{
	emit outgoingData( outgoing->toRawCommand() );
	// Clear the transfer.
	delete outgoing;
}

int MessengerCoreProtocol::rawToNetworkMessage(const QByteArray &raw)
{
	uint bytesParsed = 0;

	if ( raw.size() < 4 )
	{
		d->state = NeedMore;
		return bytesParsed;
	}

	QByteArray tempRaw = raw;
	QDataStream din( &tempRaw, QIODevice::ReadOnly );

	// look at first four bytes and decide what to do with the chunk
	if ( okToProceed( din ) )
	{
		if(d->state != WaitForPayload && d->state != NeedMore)
		{
			QTextStream lineStream(tempRaw);

			QString parsedLine = lineStream.readLine();

			QStringList commandList = parsedLine.split(" ");

			QString command;
			QStringList arguments;

			NetworkMessage::NetworkMessageType transferType;
			bool dummy, isNumber = false;
			int trId = 0, payloadLength = 0;

			command = commandList.at(0);

			// Determine the transfer type.
			if(isPayloadCommand(command))
			{
				transferType |= NetworkMessage::PayloadMessage;
				// Remove the last parameter from the command list and set the payload length.
				// So it will not be in the arguments.
				payloadLength = commandList.takeLast().toUInt(&dummy);
				qDebug() << Q_FUNC_INFO << "Begin Payload transfer, length:" << payloadLength;
			}

			// Check for a transaction ID.
			// Do not check for a transaction if the commandList size is lower than 2.
			if( commandList.size() >= 2 )
			{
				trId = commandList[1].toUInt(&isNumber);
				if(isNumber)
					transferType |= NetworkMessage::TransactionMessage;
			}

			// Begin at the third command arguments if we have a transaction ID.
			int beginAt = isNumber ? 2 : 1;
			// Fill the arguments.
			for(int i = beginAt; i < commandList.size(); ++i)
			{
				arguments << commandList[i];
			}

			NetworkMessage *receivedNetworkMessage = new NetworkMessage(transferType);
			receivedNetworkMessage->setCommand(command);
			receivedNetworkMessage->setArguments(arguments);

			if(isNumber)
				receivedNetworkMessage->setTransactionId( QString::number(trId) );

			d->inNetworkMessage = receivedNetworkMessage;

			if(payloadLength > 0)
			{
				d->payloadLength = payloadLength;
				d->state = WaitForPayload;
			}
			else
			{
				// Show parsed line here for non-payload messages.
				qDebug() << Q_FUNC_INFO << parsedLine;
				d->state = Available;
				emit incomingData();
			}

			bytesParsed = parsedLine.size() + 2; // 2 is to add \r\n to the size which was trimmed.
		}
		else if(d->state == WaitForPayload || d->state == NeedMore)
		{
			if(raw.size() < d->payloadLength)
			{
				qDebug() << Q_FUNC_INFO << "Raw size:" << raw.size() << "Payload length:" << d->payloadLength;
				d->state = NeedMore;
				return bytesParsed;
			}

			// Retrieve the full payload data from raw data (do a shared copy)
			QByteArray payloadData = raw.left(d->payloadLength);

			d->inNetworkMessage->setPayloadData(payloadData);
			qDebug() << Q_FUNC_INFO << "Byte data length:" << payloadData.size();
// 			qDebug() << Q_FUNC_INFO << "Payload data read(from CoreProtocol):" << raw;
			// Show full payload command to output
			qDebug() << Q_FUNC_INFO << d->inNetworkMessage->toRawCommand();
			d->state = Available;

			bytesParsed = payloadData.size();

			emit incomingData();
		}
	}
	return bytesParsed;
}

void MessengerCoreProtocol::reset()
{
	d->in.clear();
}

bool MessengerCoreProtocol::okToProceed(const QDataStream &din)
{
	if( din.atEnd() )
	{
		d->state = NeedMore;
		return false;
	}
	else
		return true;
}

bool MessengerCoreProtocol::isPayloadCommand(const QString &command)
{
	if( command == QLatin1String("ADL") ||
	    command == QLatin1String("GCF") ||
	    command == QLatin1String("MSG") ||
	    command == QLatin1String("QRY") ||
	    command == QLatin1String("RML") ||
	    command == QLatin1String("UBX") ||
	    command == QLatin1String("UBN") ||
	    command == QLatin1String("UUN") ||
	    command == QLatin1String("UUX")
	  )
		return true;
	else
		return false;
}

}

#include "messengercoreprotocol.moc"
//kate: indent-mode csands; tab-width 4;
<|endoftext|>


<commit_before><commit_msg>TODO-606: WIP<commit_after><|endoftext|>


<commit_before>#include "iroha/resource_attr.h"

#include "iroha/i_design.h"
#include "iroha/insn_operands.h"
#include "iroha/resource_class.h"

namespace iroha {

int ResourceAttr::NumMultiCycleInsn(const IState *st) {
  int n = 0;
  for (IInsn *insn : st->insns_) {
    if (IsMultiCycleInsn(insn)) {
      ++n;
    }
  }
  return n;
}

bool ResourceAttr::IsMultiCycleInsn(IInsn *insn) {
  IResource *res = insn->GetResource();
  IResourceClass &rc = *(res->GetClass());
  if (resource::IsTaskCall(rc) ||
      resource::IsSharedMemory(rc) ||
      resource::IsSharedMemoryReader(rc) ||
      resource::IsSharedMemoryWriter(rc) ||
      resource::IsExtTaskDone(rc) ||
      resource::IsExtTaskCall(rc) ||
      resource::IsExtTaskWait(rc)) {
    return true;
  }
  if (resource::IsStudy(rc) ||
      resource::IsStudyReader(rc) ||
      resource::IsStudyWriter(rc)) {
    return true;
  }
  if (resource::IsAxiMasterPort(rc) ||
      resource::IsAxiSlavePort(rc) ||
      resource::IsSramIf(rc)) {
    return true;
  }
  if (resource::IsFifo(rc) ||
      resource::IsFifoReader(rc)) {
    return true;
  }
  if (resource::IsFifoWriter(rc) &&
      insn->GetOperand() != operand::kNoWait) {
    return true;
  }
  if (resource::IsSharedRegReader(rc)) {
    if (insn->GetOperand() == operand::kWaitNotify ||
	insn->GetOperand() == operand::kGetMailbox) {
      return true;
    }
  }
  if (resource::IsSharedRegWriter(rc)) {
    if (insn->GetOperand() == operand::kPutMailbox) {
      return true;
    }
  }
  return false;
}

bool ResourceAttr::IsExtAccessResource(IResource *res) {
  IResourceClass &rc = *(res->GetClass());
  if (resource::IsExtInput(rc) ||
      resource::IsExtInputAccessor(rc) ||
      resource::IsExtOutput(rc) ||
      resource::IsExtOutputAccessor(rc) ||
      resource::IsAxiMasterPort(rc) ||
      resource::IsAxiSlavePort(rc) ||
      resource::IsSramIf(rc) ||
      resource::IsExtTask(rc) ||
      resource::IsExtTaskDone(rc) ||
      resource::IsExtTaskCall(rc) ||
      resource::IsExtTaskWait(rc) ||
      resource::IsSharedRegExtWriter(rc)) {
    return true;
  }
  if (resource::IsArray(rc) && res->GetArray() != nullptr &&
      res->GetArray()->IsExternal()) {
    return true;
  }
  return false;
}

bool ResourceAttr::IsExtWaitInsn(IInsn *insn) {
  IResourceClass &rc = *(insn->GetResource()->GetClass());
  return resource::IsAxiSlavePort(rc) || resource::IsSramIf(rc);
}

bool ResourceAttr::IsExtAccessInsn(IInsn *insn) {
  return IsExtAccessResource(insn->GetResource());
}

int ResourceAttr::NumExtAccessInsn(const IState *st) {
  int n = 0;
  for (IInsn *insn : st->insns_) {
    if (IsExtAccessInsn(insn)) {
      ++n;
    }
  }
  return n;
}

bool ResourceAttr::IsDuplicatableResource(IResource *res) {
  IResourceClass &rc = *(res->GetClass());
  const string &name = rc.GetName();
  // add, sub, mul, gt, gte and ext-combinational for now.
  if (name == resource::kEq) {
    return false;
  }
  if (resource::IsExtCombinational(rc)) {
    return true;
  }
  return resource::IsExclusiveBinOp(rc);
}

bool ResourceAttr::IsOrderedResource(IResource *res) {
  IResourceClass &rc = *(res->GetClass());
  if (resource::IsArray(rc) || resource::IsSharedMemoryReplica(rc)) {
    return true;
  }
  return false;
}

}  // namespace iroha
<commit_msg>Don't reorder ticker access.<commit_after>#include "iroha/resource_attr.h"

#include "iroha/i_design.h"
#include "iroha/insn_operands.h"
#include "iroha/resource_class.h"

namespace iroha {

int ResourceAttr::NumMultiCycleInsn(const IState *st) {
  int n = 0;
  for (IInsn *insn : st->insns_) {
    if (IsMultiCycleInsn(insn)) {
      ++n;
    }
  }
  return n;
}

bool ResourceAttr::IsMultiCycleInsn(IInsn *insn) {
  IResource *res = insn->GetResource();
  IResourceClass &rc = *(res->GetClass());
  if (resource::IsTaskCall(rc) ||
      resource::IsSharedMemory(rc) ||
      resource::IsSharedMemoryReader(rc) ||
      resource::IsSharedMemoryWriter(rc) ||
      resource::IsExtTaskDone(rc) ||
      resource::IsExtTaskCall(rc) ||
      resource::IsExtTaskWait(rc)) {
    return true;
  }
  if (resource::IsStudy(rc) ||
      resource::IsStudyReader(rc) ||
      resource::IsStudyWriter(rc)) {
    return true;
  }
  if (resource::IsAxiMasterPort(rc) ||
      resource::IsAxiSlavePort(rc) ||
      resource::IsSramIf(rc)) {
    return true;
  }
  if (resource::IsFifo(rc) ||
      resource::IsFifoReader(rc)) {
    return true;
  }
  if (resource::IsFifoWriter(rc) &&
      insn->GetOperand() != operand::kNoWait) {
    return true;
  }
  if (resource::IsSharedRegReader(rc)) {
    if (insn->GetOperand() == operand::kWaitNotify ||
	insn->GetOperand() == operand::kGetMailbox) {
      return true;
    }
  }
  if (resource::IsSharedRegWriter(rc)) {
    if (insn->GetOperand() == operand::kPutMailbox) {
      return true;
    }
  }
  return false;
}

bool ResourceAttr::IsExtAccessResource(IResource *res) {
  IResourceClass &rc = *(res->GetClass());
  if (resource::IsExtInput(rc) ||
      resource::IsExtInputAccessor(rc) ||
      resource::IsExtOutput(rc) ||
      resource::IsExtOutputAccessor(rc) ||
      resource::IsAxiMasterPort(rc) ||
      resource::IsAxiSlavePort(rc) ||
      resource::IsSramIf(rc) ||
      resource::IsExtTask(rc) ||
      resource::IsExtTaskDone(rc) ||
      resource::IsExtTaskCall(rc) ||
      resource::IsExtTaskWait(rc) ||
      resource::IsSharedRegExtWriter(rc)) {
    return true;
  }
  if (resource::IsArray(rc) && res->GetArray() != nullptr &&
      res->GetArray()->IsExternal()) {
    return true;
  }
  return false;
}

bool ResourceAttr::IsExtWaitInsn(IInsn *insn) {
  IResourceClass &rc = *(insn->GetResource()->GetClass());
  return resource::IsAxiSlavePort(rc) || resource::IsSramIf(rc);
}

bool ResourceAttr::IsExtAccessInsn(IInsn *insn) {
  return IsExtAccessResource(insn->GetResource());
}

int ResourceAttr::NumExtAccessInsn(const IState *st) {
  int n = 0;
  for (IInsn *insn : st->insns_) {
    if (IsExtAccessInsn(insn)) {
      ++n;
    }
  }
  return n;
}

bool ResourceAttr::IsDuplicatableResource(IResource *res) {
  IResourceClass &rc = *(res->GetClass());
  const string &name = rc.GetName();
  // add, sub, mul, gt, gte and ext-combinational for now.
  if (name == resource::kEq) {
    return false;
  }
  if (resource::IsExtCombinational(rc)) {
    return true;
  }
  return resource::IsExclusiveBinOp(rc);
}

bool ResourceAttr::IsOrderedResource(IResource *res) {
  IResourceClass &rc = *(res->GetClass());
  if (resource::IsArray(rc) || resource::IsSharedMemoryReplica(rc) || resource::IsTicker(rc)) {
    return true;
  }
  return false;
}

}  // namespace iroha
<|endoftext|>


<commit_before>#include "HMC5883L.h"
#include "Wire.h"

void
HMC5883L::begin(){

    Wire.begin();
    Wire.setClock(800000L);
    delay(10);

    Wire.beginTransmission(address);
    Wire.write((uint8_t) 0x00);
    Wire.write((uint8_t) 0x70);
    Wire.endTransmission();

    Wire.beginTransmission(address);
    Wire.write((uint8_t) 0x01);
    Wire.write((uint8_t) 0x00);
    Wire.endTransmission();
}
void
HMC5883L::tune(LTATune t){
    LTA = t;
}
void
HMC5883L::end(){

}
bool
HMC5883L::checkGoodValues() {
    /*perform the original check that looks for a good status bit */
    Wire.beginTransmission(address);
    Wire.write((uint8_t)0x09);
    Wire.endTransmission();
    Wire.requestFrom(address, (uint8_t)0x01);
    if (Wire.available() >= 1) {
        uint8_t status = Wire.read();
        if ((status & 0x3) == 1) return true;
    }

    /*bad return value: either compass failed or is clone. */
    /*if not reporting as a good HMC5883L then check the values returned by the compass to determine if it is ok*/
    int m[3];
    rawValues(m[0], m[1], m[2]);
    float mag = (float)(m[0] * m[0] + m[1] * m[1]);
    mag = sqrt(mag);
    bool isGood = true;
    if (mag >= HMC5883L_MAX_EXPECTED_VALUE_MAG || mag <= HMC5883L_MIN_EXPECTED_VALUE_MAG)
        isGood = false;
    int zmag = abs(m[2]);
    isGood=( isGood && (zmag <= HMC5883L_MAX_EXPECTED_VALUE_MAG));
    if (isGood) return true; //check if cloned compass is returning reasonable values, if so go on.
    /*#HMCFAIL HMC5883L Compass sensor failed contact or reported bad status*/
    return false;
}
Sensor::Status
HMC5883L::status()
{
    /*check if compass is the original HMC5883L or a clone*/
    isTrueHMC5883L = true;
    Wire.beginTransmission(address);
    Wire.write((uint8_t)0x09);
    Wire.endTransmission();
    Wire.requestFrom(address, (uint8_t)0x01);
    if (Wire.available() >= 1) {
        uint8_t status = Wire.read();
        if ((status & 0x3) == 1) return Sensor::OK; //always return ok here
    }

    isTrueHMC5883L = false;//bad return value either compass failed or is clone. Set compass as clone.
    return Sensor::OK; //always return sensor ok here, this function is called when board is powered on, good values will be checked at arming time.
}
void
HMC5883L::calibrate(){

}
void
HMC5883L::update(InertialManager& man, Translator axis){
    int m[3];
    rawValues(m[0], m[1], m[2]);
    float M[3];
    LTA.calibrate<int>(m,M);
    man.mag = axis(M);
}
void
HMC5883L::rawValues(int& x, int& y, int& z) {
    Wire.beginTransmission(address);
    if (isTrueHMC5883L) {
        Wire.write((uint8_t)0x02);
        Wire.write((uint8_t)0x01);
    }
    else {
        Wire.write((uint8_t)0x03);
    }
    Wire.endTransmission();

    Wire.requestFrom(address, (uint8_t)0x06);
    if(Wire.available()>=6){
        uint8_t* d = (uint8_t*) &x;
        d[1] = Wire.read();
        d[0] = Wire.read();
        d = (uint8_t*) &z;
        d[1] = Wire.read();
        d[0] = Wire.read();
        d = (uint8_t*) &y;
        d[1] = Wire.read();
        d[0] = Wire.read();
    }
}
float
HMC5883L::getAzimuth(){
    int m[3];
    rawValues(m[0], m[1], m[2]);
    float M[3];
    for(int i=0; i<3; i++){
        M[i]  = m[i];
        M[i] += LTA.shift[i];
        M[i] *= LTA.scalar[i];
    }
    return atan2(M[0], M[1]);
}
<commit_msg>fix accidental commit to master<commit_after><|endoftext|>