<commit_before>/*
 * TTBlue Audio Object Base Class
 * Copyright © 2008, Timothy Place
 *
 * License: This code is licensed under the terms of the GNU LGPL
 * http://www.gnu.org/licenses/lgpl.html
 */

#include "TTAudioObject.h"
#include "TTEnvironment.h"

// This coeff is used in GainDataspace mapping MIDI to and from linear gain
// so that MIDI=100 equals 0 dB and MIDI = 127 equals +10 dB
static const double kGainMidiPower = log(pow(10.,10./20.))/log(127./100.);
static const double kGainMidiPowerInv = 1./kGainMidiPower;

/****************************************************************************************************/

TTAudioObject::TTAudioObject(const char* name, TTUInt16 newMaxNumChannels)
	: TTObject(name), attrMute(0)
{
	registerAttribute(TT("maxNumChannels"), kTypeUInt8,		&maxNumChannels,	(TTSetterMethod)&TTAudioObject::setMaxNumChannels);
	registerAttribute(TT("sr"),				kTypeUInt32,	&sr,				(TTSetterMethod)&TTAudioObject::setSr);
	registerAttribute(TT("bypass"),			kTypeBoolean,	&attrBypass,		(TTSetterMethod)&TTAudioObject::setBypass);
	registerAttribute(TT("mute"),			kTypeBoolean,	&attrMute,			(TTSetterMethod)&TTAudioObject::setMute);
	registerAttribute(TT("processInPlace"), kTypeBoolean,	&attrProcessInPlace);

	// Set Defaults...

	// Commenting this out, thus making this initial argument unused.
	// The problem is that if we set it here, then it is too early to trigger the notification in the subclass.
	// And then because it is already defined, then our repetition filtering won't let it through to allocate memory...
	// setAttributeValue(TT("maxNumChannels"),	newMaxNumChannels);

	inputArray = new TTAudioSignalArray(2);
	outputArray = new TTAudioSignalArray(2);

	setAttributeValue(TT("sr"),				ttEnvironment->sr);
	setProcess(&TTAudioObject::bypassProcess);
	setAttributeValue(TT("bypass"),			*kTTBoolNo);
	setAttributeValue(TT("processInPlace"), *kTTBoolNo);
}

TTAudioObject::~TTAudioObject()
{
	delete inputArray;
	delete outputArray;
}

TTErr TTAudioObject::setMaxNumChannels(const TTValue& newValue)
{
	if(TTUInt16(newValue) != maxNumChannels){
		TTValue	oldMaxNumChannels = maxNumChannels;

		maxNumChannels = newValue;
		sendMessage(TT("updateMaxNumChannels"), oldMaxNumChannels);
	}
	return kTTErrNone;
}

TTErr TTAudioObject::setSr(const TTValue& newValue)
{
	sr = newValue;
	srInv = 1.0/sr;
	srMill = sr * 0.001;
	sendMessage(TT("updateSr"));
	return kTTErrNone;
}

TTErr TTAudioObject::bypassProcess(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
{
	for(TTUInt16 i=0; i<outputs->numAudioSignals; i++){
		TTAudioSignal& out = outputs->getSignal(i);

		if(i<inputs->numAudioSignals){
			TTAudioSignal& in = inputs->getSignal(i);
			TTAudioSignal::copy(in, out);
		}
		else
			out.clear();
	}
	return kTTErrNone;
}

TTErr TTAudioObject::bypassCalculate(const TTFloat64& x, TTFloat64& y)
{
	y = x;
	return kTTErrNone;
}

TTErr TTAudioObject::muteProcess(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
{
	for(TTUInt16 i=0; i<inputs->numAudioSignals; i++)
		(inputs->getSignal(i)).clear();
	for(TTUInt16 i=0; i<outputs->numAudioSignals; i++)
		(outputs->getSignal(i)).clear();
	return kTTErrNone;
}

TTErr TTAudioObject::defaultCalculateMethod(const TTFloat64& x, TTFloat64& y)
{
	TTAudioSignal	in(1);
	TTAudioSignal	out(1);
	TTErr			err;

	in.setvectorSize(1);
	out.setvectorSize(1);

	in.sampleVectors[0][0] = x;
	err = process(in, out);
	y = out.sampleVectors[0][0];

	return err;
}

TTErr TTAudioObject::setProcess(TTProcessMethod newProcessMethod)
{
	processMethod = newProcessMethod;
	if(!calculateMethod)
		calculateMethod = &TTAudioObject::defaultCalculateMethod;

	if(!attrBypass){
		currentProcessMethod = processMethod;
		currentCalculateMethod = calculateMethod;
	}
	return kTTErrNone;
}

TTErr TTAudioObject::setCalculate(TTCalculateMethod newCalculateMethod)
{
	calculateMethod = newCalculateMethod;
	if(!attrBypass)
		currentCalculateMethod = calculateMethod;
	return kTTErrNone;
}

TTErr TTAudioObject::setBypass(const TTValue& value)
{
	attrBypass = value;
	if(attrBypass){
		currentProcessMethod = &TTAudioObject::bypassProcess;
		currentCalculateMethod = &TTAudioObject::bypassCalculate;
	}
	else if(attrMute){
		currentProcessMethod = &TTAudioObject::muteProcess;
	}
	else{
		currentProcessMethod = processMethod;
		if(calculateMethod)
			currentCalculateMethod = calculateMethod;
		else
			currentCalculateMethod = &TTAudioObject::defaultCalculateMethod;
	}
	return kTTErrNone;
}

TTErr TTAudioObject::setMute(const TTValue& value)
{
	attrMute = value;
	if(attrBypass){
		currentProcessMethod = &TTAudioObject::bypassProcess;
	}
	else if(attrMute){
		currentProcessMethod = &TTAudioObject::muteProcess;
	}
	else{
		currentProcessMethod = processMethod;
	}
	return kTTErrNone;
}

TTErr TTAudioObject::calculate(const TTFloat64& x, TTFloat64& y)
{
	TTErr	err;

	if(valid){
		lock();
		err = (this->*currentCalculateMethod)(x, y);
		unlock();
	}
	return err;
}

TTErr TTAudioObject::process(TTAudioSignal& in, TTAudioSignal& out)
{
	TTErr	err;

	if(valid){
		lock();
		inputArray->numAudioSignals = 1;
		inputArray->setSignal(0, &in);
		outputArray->numAudioSignals = 1;
		outputArray->setSignal(0, &out);
		err = (this->*currentProcessMethod)(inputArray, outputArray);
		unlock();
	}
	return err;
}

TTErr TTAudioObject::process(TTAudioSignal& out)
{
	TTErr	err;

	if(valid){
		lock();
		inputArray->numAudioSignals = 0;
		outputArray->numAudioSignals = 1;
		outputArray->setSignal(0, &out);
		err = (this->*currentProcessMethod)(inputArray, outputArray);
		unlock();
	}
	return err;
}

TTErr TTAudioObject::process(TTAudioSignal& in1, TTAudioSignal& in2, TTAudioSignal& out1, TTAudioSignal& out2)
{
	TTErr	err;

	if(valid){
		lock();
		inputArray->numAudioSignals = 2;
		inputArray->setSignal(0, &in1);
		inputArray->setSignal(1, &in2);
		outputArray->numAudioSignals = 2;
		outputArray->setSignal(0, &out1);
		outputArray->setSignal(1, &out2);
		err = (this->*currentProcessMethod)(inputArray, outputArray);
		unlock();
	}
	return err;
}

TTErr TTAudioObject::process(TTAudioSignal& in1, TTAudioSignal& in2, TTAudioSignal& out)
{
	TTErr	err;

	if(valid){
		lock();
		inputArray->numAudioSignals = 2;
		inputArray->setSignal(0, &in1);
		inputArray->setSignal(1, &in2);
		outputArray->numAudioSignals = 1;
		outputArray->setSignal(0, &out);
		err = (this->*currentProcessMethod)(inputArray, outputArray);
		unlock();
	}
	return err;
}

TTErr TTAudioObject::process(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
{
	TTErr	err;

	if(valid){
		lock();
		err = (this->*currentProcessMethod)(inputs, outputs);
		unlock();
	}
	return err;
}

#if 0
#pragma mark -
#pragma mark Utilities
#endif

// RADIANS CONVERSIONS: cannot make static because of access to a member data element
// hz-to-radians conversion
TTFloat64 TTAudioObject::hertzToRadians(const TTFloat64 hz)			// NOTE: Be sure to set the sr before calling this function
{
	return(hz * (kTTPi / (sr * 0.5)));
}

// radians-to-hz conversion
TTFloat64 TTAudioObject::radiansToHertz(const TTFloat64 radians)	// NOTE: Be sure to set the sr before calling this function
{
	return((radians * sr) / kTTTwoPi);
}

// degrees-to-radians conversion
TTFloat64 TTAudioObject::degreesToRadians(const TTFloat64 degrees)
{
	return((degrees * kTTPi) / 180.);
}

// radians-to-degrees conversion
TTFloat64 TTAudioObject::radiansToDegrees(const TTFloat64 radians)
{
	return((radians * 180.) / kTTPi);
}

// Decay Time (seconds) to feedback coefficient conversion
TTFloat64 TTAudioObject::decayToFeedback(const TTFloat64 decay_time, TTFloat64 delay)
{
	TTFloat64 	fb;

	delay = delay * 0.001;			// convert delay from milliseconds to seconds
	if(decay_time < 0){
		fb = delay / -decay_time;
		fb = fb * -60.;
		fb = pow(10., (fb / 20.));
		fb *= -1.;
	}
	else{
		fb = delay / decay_time;
		fb = fb * -60.;
		fb = pow(10., (fb / 20.));
	}
	return(fb);
}

// return the decay time based on the feedback coefficient
TTFloat64 TTAudioObject::feedbackToDecay(const TTFloat64 feedback, const TTFloat64 delay)
{
	TTFloat64 	decay_time;

	if(feedback > 0){
		decay_time = 20. * (log10(feedback));
		decay_time = -60.0 / decay_time;
		decay_time = decay_time * (delay);
	}
	else if(feedback < 0){
		decay_time = 20. * (log10(fabs(feedback)));
		decay_time = -60.0 / decay_time;
		decay_time = decay_time * (-delay);
	}
	else
		decay_time = 0;

	return(decay_time);
}

// ************* DECIBEL CONVERSIONS **************

// Amplitude to decibels
TTFloat64 TTAudioObject::linearToDb(const TTFloat64 value)
{
	if(value >= 0)
		return(20. * (log10(value)));
	else
	 	return 0;
}

// Decibels to amplitude
TTFloat64 TTAudioObject::dbToLinear(TTFloat64 value)
{
	return(pow(10., (value / 20.)));
}

TTFloat64 TTAudioObject::midiToLinearGain(TTFloat64 value)
{
	return pow(value * 0.01, kGainMidiPower);
}

TTFloat64 TTAudioObject::linearGainToMidi(TTFloat64 value)
{
	return 100.0 * pow(value, kGainMidiPowerInv);
}

// Deviate
TTFloat64 TTAudioObject::deviate(TTFloat64 value)
{
	value += (2.0 * (TTFloat32(rand()) / TTFloat32(RAND_MAX))) - 1.0;	// randomize input with +1 to -1 ms
	value = value * 0.001 * sr;											// convert from ms to samples
	value = (TTFloat32)prime(TTUInt32(value));							// find the nearest prime number (in samples)
	value = (value / sr) * 1000.0;										// convert back to ms

	return value;
}

// Prime
TTUInt32 TTAudioObject::prime(TTUInt32 value)
{
	long	candidate, last, i, isPrime;

   	if(value < 2)
  		candidate = 2;
	else if(value == 2)
		candidate = 3;
	else{
		candidate = value;
		if (candidate % 2 == 0)								// Test only odd numbers
			candidate--;
		do{
			isPrime = true;									// Assume glorious success
			candidate += 2;									// Bump to the next number to test
			last = TTUInt32(sqrt((TTFloat32)candidate));  	// We'll check to see if candidate has any factors, from 2 to last
			for (i=3; (i <= last) && isPrime; i+=2){		// Loop through odd numbers only
				if((candidate % i) == 0)
				isPrime = false;
			}
		}
		while (!isPrime);
	}
	return candidate;
}

<commit_msg>initializing variables<commit_after>/*
 * TTBlue Audio Object Base Class
 * Copyright © 2008, Timothy Place
 *
 * License: This code is licensed under the terms of the GNU LGPL
 * http://www.gnu.org/licenses/lgpl.html
 */

#include "TTAudioObject.h"
#include "TTEnvironment.h"

// This coeff is used in GainDataspace mapping MIDI to and from linear gain
// so that MIDI=100 equals 0 dB and MIDI = 127 equals +10 dB
static const double kGainMidiPower = log(pow(10.,10./20.))/log(127./100.);
static const double kGainMidiPowerInv = 1./kGainMidiPower;

/****************************************************************************************************/

TTAudioObject::TTAudioObject(const char* name, TTUInt16 newMaxNumChannels)
	: TTObject(name), attrMute(0)
{
	registerAttribute(TT("maxNumChannels"), kTypeUInt8,		&maxNumChannels,	(TTSetterMethod)&TTAudioObject::setMaxNumChannels);
	registerAttribute(TT("sr"),				kTypeUInt32,	&sr,				(TTSetterMethod)&TTAudioObject::setSr);
	registerAttribute(TT("bypass"),			kTypeBoolean,	&attrBypass,		(TTSetterMethod)&TTAudioObject::setBypass);
	registerAttribute(TT("mute"),			kTypeBoolean,	&attrMute,			(TTSetterMethod)&TTAudioObject::setMute);
	registerAttribute(TT("processInPlace"), kTypeBoolean,	&attrProcessInPlace);

	// Set Defaults...

	// Commenting this out, thus making this initial argument unused.
	// The problem is that if we set it here, then it is too early to trigger the notification in the subclass.
	// And then because it is already defined, then our repetition filtering won't let it through to allocate memory...
	// setAttributeValue(TT("maxNumChannels"),	newMaxNumChannels);

	inputArray = new TTAudioSignalArray(2);
	outputArray = new TTAudioSignalArray(2);

	setAttributeValue(TT("sr"),				ttEnvironment->sr);
	setProcess(&TTAudioObject::bypassProcess);
	setAttributeValue(TT("bypass"),			*kTTBoolNo);
	setAttributeValue(TT("processInPlace"), *kTTBoolNo);
}

TTAudioObject::~TTAudioObject()
{
	delete inputArray;
	delete outputArray;
}

TTErr TTAudioObject::setMaxNumChannels(const TTValue& newValue)
{
	if(TTUInt16(newValue) != maxNumChannels){
		TTValue	oldMaxNumChannels = maxNumChannels;

		maxNumChannels = newValue;
		sendMessage(TT("updateMaxNumChannels"), oldMaxNumChannels);
	}
	return kTTErrNone;
}

TTErr TTAudioObject::setSr(const TTValue& newValue)
{
	sr = newValue;
	srInv = 1.0/sr;
	srMill = sr * 0.001;
	sendMessage(TT("updateSr"));
	return kTTErrNone;
}

TTErr TTAudioObject::bypassProcess(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
{
	for(TTUInt16 i=0; i<outputs->numAudioSignals; i++){
		TTAudioSignal& out = outputs->getSignal(i);

		if(i<inputs->numAudioSignals){
			TTAudioSignal& in = inputs->getSignal(i);
			TTAudioSignal::copy(in, out);
		}
		else
			out.clear();
	}
	return kTTErrNone;
}

TTErr TTAudioObject::bypassCalculate(const TTFloat64& x, TTFloat64& y)
{
	y = x;
	return kTTErrNone;
}

TTErr TTAudioObject::muteProcess(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
{
	for(TTUInt16 i=0; i<inputs->numAudioSignals; i++)
		(inputs->getSignal(i)).clear();
	for(TTUInt16 i=0; i<outputs->numAudioSignals; i++)
		(outputs->getSignal(i)).clear();
	return kTTErrNone;
}

TTErr TTAudioObject::defaultCalculateMethod(const TTFloat64& x, TTFloat64& y)
{
	TTAudioSignal	in(1);
	TTAudioSignal	out(1);
	TTErr			err;

	in.setvectorSize(1);
	out.setvectorSize(1);

	in.sampleVectors[0][0] = x;
	err = process(in, out);
	y = out.sampleVectors[0][0];

	return err;
}

TTErr TTAudioObject::setProcess(TTProcessMethod newProcessMethod)
{
	processMethod = newProcessMethod;
	if(!calculateMethod)
		calculateMethod = &TTAudioObject::defaultCalculateMethod;

	if(!attrBypass){
		currentProcessMethod = processMethod;
		currentCalculateMethod = calculateMethod;
	}
	return kTTErrNone;
}

TTErr TTAudioObject::setCalculate(TTCalculateMethod newCalculateMethod)
{
	calculateMethod = newCalculateMethod;
	if(!attrBypass)
		currentCalculateMethod = calculateMethod;
	return kTTErrNone;
}

TTErr TTAudioObject::setBypass(const TTValue& value)
{
	attrBypass = value;
	if(attrBypass){
		currentProcessMethod = &TTAudioObject::bypassProcess;
		currentCalculateMethod = &TTAudioObject::bypassCalculate;
	}
	else if(attrMute){
		currentProcessMethod = &TTAudioObject::muteProcess;
	}
	else{
		currentProcessMethod = processMethod;
		if(calculateMethod)
			currentCalculateMethod = calculateMethod;
		else
			currentCalculateMethod = &TTAudioObject::defaultCalculateMethod;
	}
	return kTTErrNone;
}

TTErr TTAudioObject::setMute(const TTValue& value)
{
	attrMute = value;
	if(attrBypass){
		currentProcessMethod = &TTAudioObject::bypassProcess;
	}
	else if(attrMute){
		currentProcessMethod = &TTAudioObject::muteProcess;
	}
	else{
		currentProcessMethod = processMethod;
	}
	return kTTErrNone;
}

TTErr TTAudioObject::calculate(const TTFloat64& x, TTFloat64& y)
{
	TTErr	err = kTTErrGeneric;

	if(valid){
		lock();
		err = (this->*currentCalculateMethod)(x, y);
		unlock();
	}
	return err;
}

TTErr TTAudioObject::process(TTAudioSignal& in, TTAudioSignal& out)
{
	TTErr	err = kTTErrGeneric;

	if(valid){
		lock();
		inputArray->numAudioSignals = 1;
		inputArray->setSignal(0, &in);
		outputArray->numAudioSignals = 1;
		outputArray->setSignal(0, &out);
		err = (this->*currentProcessMethod)(inputArray, outputArray);
		unlock();
	}
	return err;
}

TTErr TTAudioObject::process(TTAudioSignal& out)
{
	TTErr	err = kTTErrGeneric;

	if(valid){
		lock();
		inputArray->numAudioSignals = 0;
		outputArray->numAudioSignals = 1;
		outputArray->setSignal(0, &out);
		err = (this->*currentProcessMethod)(inputArray, outputArray);
		unlock();
	}
	return err;
}

TTErr TTAudioObject::process(TTAudioSignal& in1, TTAudioSignal& in2, TTAudioSignal& out1, TTAudioSignal& out2)
{
	TTErr	err = kTTErrGeneric;

	if(valid){
		lock();
		inputArray->numAudioSignals = 2;
		inputArray->setSignal(0, &in1);
		inputArray->setSignal(1, &in2);
		outputArray->numAudioSignals = 2;
		outputArray->setSignal(0, &out1);
		outputArray->setSignal(1, &out2);
		err = (this->*currentProcessMethod)(inputArray, outputArray);
		unlock();
	}
	return err;
}

TTErr TTAudioObject::process(TTAudioSignal& in1, TTAudioSignal& in2, TTAudioSignal& out)
{
	TTErr	err = kTTErrGeneric;

	if(valid){
		lock();
		inputArray->numAudioSignals = 2;
		inputArray->setSignal(0, &in1);
		inputArray->setSignal(1, &in2);
		outputArray->numAudioSignals = 1;
		outputArray->setSignal(0, &out);
		err = (this->*currentProcessMethod)(inputArray, outputArray);
		unlock();
	}
	return err;
}

TTErr TTAudioObject::process(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs)
{
	TTErr	err = kTTErrGeneric;

	if(valid){
		lock();
		err = (this->*currentProcessMethod)(inputs, outputs);
		unlock();
	}
	return err;
}

#if 0
#pragma mark -
#pragma mark Utilities
#endif

// RADIANS CONVERSIONS: cannot make static because of access to a member data element
// hz-to-radians conversion
TTFloat64 TTAudioObject::hertzToRadians(const TTFloat64 hz)			// NOTE: Be sure to set the sr before calling this function
{
	return(hz * (kTTPi / (sr * 0.5)));
}

// radians-to-hz conversion
TTFloat64 TTAudioObject::radiansToHertz(const TTFloat64 radians)	// NOTE: Be sure to set the sr before calling this function
{
	return((radians * sr) / kTTTwoPi);
}

// degrees-to-radians conversion
TTFloat64 TTAudioObject::degreesToRadians(const TTFloat64 degrees)
{
	return((degrees * kTTPi) / 180.);
}

// radians-to-degrees conversion
TTFloat64 TTAudioObject::radiansToDegrees(const TTFloat64 radians)
{
	return((radians * 180.) / kTTPi);
}

// Decay Time (seconds) to feedback coefficient conversion
TTFloat64 TTAudioObject::decayToFeedback(const TTFloat64 decay_time, TTFloat64 delay)
{
	TTFloat64 	fb;

	delay = delay * 0.001;			// convert delay from milliseconds to seconds
	if(decay_time < 0){
		fb = delay / -decay_time;
		fb = fb * -60.;
		fb = pow(10., (fb / 20.));
		fb *= -1.;
	}
	else{
		fb = delay / decay_time;
		fb = fb * -60.;
		fb = pow(10., (fb / 20.));
	}
	return(fb);
}

// return the decay time based on the feedback coefficient
TTFloat64 TTAudioObject::feedbackToDecay(const TTFloat64 feedback, const TTFloat64 delay)
{
	TTFloat64 	decay_time;

	if(feedback > 0){
		decay_time = 20. * (log10(feedback));
		decay_time = -60.0 / decay_time;
		decay_time = decay_time * (delay);
	}
	else if(feedback < 0){
		decay_time = 20. * (log10(fabs(feedback)));
		decay_time = -60.0 / decay_time;
		decay_time = decay_time * (-delay);
	}
	else
		decay_time = 0;

	return(decay_time);
}

// ************* DECIBEL CONVERSIONS **************

// Amplitude to decibels
TTFloat64 TTAudioObject::linearToDb(const TTFloat64 value)
{
	if(value >= 0)
		return(20. * (log10(value)));
	else
	 	return 0;
}

// Decibels to amplitude
TTFloat64 TTAudioObject::dbToLinear(TTFloat64 value)
{
	return(pow(10., (value / 20.)));
}

TTFloat64 TTAudioObject::midiToLinearGain(TTFloat64 value)
{
	return pow(value * 0.01, kGainMidiPower);
}

TTFloat64 TTAudioObject::linearGainToMidi(TTFloat64 value)
{
	return 100.0 * pow(value, kGainMidiPowerInv);
}

// Deviate
TTFloat64 TTAudioObject::deviate(TTFloat64 value)
{
	value += (2.0 * (TTFloat32(rand()) / TTFloat32(RAND_MAX))) - 1.0;	// randomize input with +1 to -1 ms
	value = value * 0.001 * sr;											// convert from ms to samples
	value = (TTFloat32)prime(TTUInt32(value));							// find the nearest prime number (in samples)
	value = (value / sr) * 1000.0;										// convert back to ms

	return value;
}

// Prime
TTUInt32 TTAudioObject::prime(TTUInt32 value)
{
	long	candidate, last, i, isPrime;

   	if(value < 2)
  		candidate = 2;
	else if(value == 2)
		candidate = 3;
	else{
		candidate = value;
		if (candidate % 2 == 0)								// Test only odd numbers
			candidate--;
		do{
			isPrime = true;									// Assume glorious success
			candidate += 2;									// Bump to the next number to test
			last = TTUInt32(sqrt((TTFloat32)candidate));  	// We'll check to see if candidate has any factors, from 2 to last
			for (i=3; (i <= last) && isPrime; i+=2){		// Loop through odd numbers only
				if((candidate % i) == 0)
				isPrime = false;
			}
		}
		while (!isPrime);
	}
	return candidate;
}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2010 Tommi Maekitalo
 *
 * 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.1 of the License, or (at your option) any later version.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "serverimpl.h"
#include "worker.h"
#include <cxxtools/eventloop.h>
#include <cxxtools/log.h>
#include "listener.h"

log_define("cxxtools.http.server.impl")

namespace cxxtools
{
namespace http
{

ServerImpl::ServerImpl(EventLoopBase& eventLoop, Signal<Server::Runmode>& runmodeChanged)
    : _eventLoop(eventLoop),
      inputSlot(slot(*this, &ServerImpl::onInput)),
      timeoutSlot(slot(*this, &ServerImpl::onTimeout)),
      _readTimeout(20000),
      _writeTimeout(20000),
      _keepAliveTimeout(30000),
      _idleTimeout(100),
      _minThreads(5),
      _maxThreads(200),
      _runmodeChanged(runmodeChanged),
      _runmode(Server::Stopped)
{
    _eventLoop.event.subscribe(slot(*this, &ServerImpl::onIdleSocket));
    _eventLoop.event.subscribe(slot(*this, &ServerImpl::onActiveSocket));
    _eventLoop.event.subscribe(slot(*this, &ServerImpl::onKeepAliveTimeout));
    _eventLoop.event.subscribe(slot(*this, &ServerImpl::onNoWaitingThreads));
    _eventLoop.event.subscribe(slot(*this, &ServerImpl::onThreadTerminated));
    _eventLoop.event.subscribe(slot(*this, &ServerImpl::onServerStart));

    connect(_eventLoop.exited, *this, &ServerImpl::terminate);

    _eventLoop.commitEvent(ServerStartEvent(this));
}

ServerImpl::~ServerImpl()
{
    if (_runmode == Server::Running)
    {
        try
        {
            terminate();
        }
        catch (const std::exception& e)
        {
            log_fatal("exception in http-server termination occured: " << e.what());
        }
    }
}

void ServerImpl::listen(const std::string& ip, unsigned short int port, int backlog)
{
    log_debug("listen on " << ip << " port " << port);
    Listener* listener = new Listener(ip, port, backlog, net::TcpServer::DEFER_ACCEPT);
    try
    {
        _listener.push_back(listener);
        _queue.put(new Socket(*this, *listener));
    }
    catch (...)
    {
        delete listener;
        throw;
    }
}

void ServerImpl::start()
{
    log_trace("start server");
    runmode(Server::Starting);

    // SIGPIPE must be ignored
    ::signal(SIGPIPE, SIG_IGN);

    MutexLock lock(_threadMutex);
    while (_threads.size() < _minThreads)
    {
        Worker* worker = new Worker(*this);
        _threads.insert(worker);
        worker->start();
    }

    runmode(Server::Running);
}

void ServerImpl::terminate()
{
    log_trace("terminate");

    MutexLock lock(_threadMutex);

    runmode(Server::Terminating);

    try
    {
        log_debug("wake " << _listener.size() << " listeners");
        for (ServerImpl::ListenerType::iterator it = _listener.begin(); it != _listener.end(); ++it)
            (*it)->wakeConnect();
        _queue.put(0);

        log_debug("terminate " << _threads.size() << " threads");
        while (!_threads.empty() || !_terminatedThreads.empty())
        {
            if (!_threads.empty())
            {
                log_debug("wait for terminated thread");
                _threadTerminated.wait(lock);
            }

            for (Threads::iterator it = _terminatedThreads.begin();
                it != _terminatedThreads.end(); ++it)
            {
                log_debug("join thread");
                (*it)->join();
                delete *it;
            }

            _terminatedThreads.clear();
        }

        log_debug("delete " << _listener.size() << " listeners");
        for (ServerImpl::ListenerType::iterator it = _listener.begin(); it != _listener.end(); ++it)
            delete *it;
        _listener.clear();

        while (!_queue.empty())
            delete _queue.get();

        for (std::set<Socket*>::iterator it = _idleSockets.begin(); it != _idleSockets.end(); ++it)
            delete *it;

        runmode(Server::Stopped);
    }
    catch (const std::exception& e)
    {
        runmode(Server::Failed);
    }
}

void ServerImpl::noWaitingThreads()
{
    MutexLock lock(_threadMutex);
    if (_runmode == Server::Running)
        _eventLoop.commitEvent(NoWaitingThreadsEvent());
}

void ServerImpl::threadTerminated(Worker* worker)
{
    MutexLock lock(_threadMutex);

    _threads.erase(worker);
    if (_runmode == Server::Running)
    {
        _eventLoop.commitEvent(ThreadTerminatedEvent(worker));
    }
    else
    {
        _terminatedThreads.insert(worker);
        _threadTerminated.signal();
    }
}

void ServerImpl::addIdleSocket(Socket* socket)
{
    log_debug("add idle socket " << static_cast<void*>(socket));

    if (_runmode == Server::Running)
    {
        _eventLoop.commitEvent(IdleSocketEvent(socket));
    }
    else
    {
        log_debug("server not running; delete " << static_cast<void*>(socket));
        delete socket;
    }
}

void ServerImpl::onIdleSocket(const IdleSocketEvent& event)
{
    Socket* socket = event.socket();

    log_debug("add idle socket " << static_cast<void*>(socket) << " to selector");

    _idleSockets.insert(socket);
    socket->setSelector(&_eventLoop);
    socket->inputConnection = connect(socket->inputReady, inputSlot);
    socket->timeoutConnection = connect(socket->timeout, timeoutSlot);
}

void ServerImpl::onActiveSocket(const ActiveSocketEvent& event)
{
    _queue.put(event.socket());
}

void ServerImpl::onNoWaitingThreads(const NoWaitingThreadsEvent& event)
{
    MutexLock lock(_threadMutex);

    if (_threads.size() >= maxThreads())
    {
        log_warn("thread limit " << maxThreads() << " reached");
        return;
    }

    try
    {
        Worker* worker = new Worker(*this);
        try
        {
            log_debug("create thread " << static_cast<void*>(worker) << "; running threads=" << _threads.size());
            worker->start();
            _threads.insert(worker);

            log_debug(_threads.size() << " threads running");
        }
        catch (const std::exception&)
        {
            delete worker;
            throw;
        }
    }
    catch (const std::exception& e)
    {
        log_warn("failed to create thread: " << e.what());
    }
}

void ServerImpl::onThreadTerminated(const ThreadTerminatedEvent& event)
{
    MutexLock lock(_threadMutex);
    log_debug("thread terminated (" << static_cast<void*>(event.worker()) << ") " << _threads.size() << " threads left");
    try
    {
        event.worker()->join();
    }
    catch (const std::exception& e)
    {
        log_error("failed to join thread: " << e.what());
    }

    delete event.worker();
}

void ServerImpl::onServerStart(const ServerStartEvent& event)
{
    if (event.server() == this)
    {
        start();
    }
}

void ServerImpl::onInput(Socket& socket)
{
    socket.removeSelector();
    log_debug("search socket " << static_cast<void*>(&socket) << " in idle sockets");
    _idleSockets.erase(&socket);

    if (socket.isConnected())
    {
        socket.inputConnection.close();
        socket.timeoutConnection.close();
        _eventLoop.commitEvent(ActiveSocketEvent(&socket));
    }
    else
    {
        log_debug("onInput; delete " << static_cast<void*>(&socket));
        delete &socket;
    }
}

void ServerImpl::onTimeout(Socket& socket)
{
    log_debug("timeout; socket " << static_cast<void*>(&socket));

    _eventLoop.commitEvent(KeepAliveTimeoutEvent(&socket));
}

void ServerImpl::onKeepAliveTimeout(const KeepAliveTimeoutEvent& event)
{
    Socket* socket = event.socket();
    _idleSockets.erase(socket);
    log_debug("onKeepAliveTimeout; delete " << static_cast<void*>(&socket));
    delete socket;
}

}
}
<commit_msg>add missing header<commit_after>/*
 * Copyright (C) 2010 Tommi Maekitalo
 *
 * 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.1 of the License, or (at your option) any later version.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "serverimpl.h"
#include "worker.h"
#include <cxxtools/eventloop.h>
#include <cxxtools/log.h>
#include "listener.h"
#include <signal.h>

log_define("cxxtools.http.server.impl")

namespace cxxtools
{
namespace http
{

ServerImpl::ServerImpl(EventLoopBase& eventLoop, Signal<Server::Runmode>& runmodeChanged)
    : _eventLoop(eventLoop),
      inputSlot(slot(*this, &ServerImpl::onInput)),
      timeoutSlot(slot(*this, &ServerImpl::onTimeout)),
      _readTimeout(20000),
      _writeTimeout(20000),
      _keepAliveTimeout(30000),
      _idleTimeout(100),
      _minThreads(5),
      _maxThreads(200),
      _runmodeChanged(runmodeChanged),
      _runmode(Server::Stopped)
{
    _eventLoop.event.subscribe(slot(*this, &ServerImpl::onIdleSocket));
    _eventLoop.event.subscribe(slot(*this, &ServerImpl::onActiveSocket));
    _eventLoop.event.subscribe(slot(*this, &ServerImpl::onKeepAliveTimeout));
    _eventLoop.event.subscribe(slot(*this, &ServerImpl::onNoWaitingThreads));
    _eventLoop.event.subscribe(slot(*this, &ServerImpl::onThreadTerminated));
    _eventLoop.event.subscribe(slot(*this, &ServerImpl::onServerStart));

    connect(_eventLoop.exited, *this, &ServerImpl::terminate);

    _eventLoop.commitEvent(ServerStartEvent(this));
}

ServerImpl::~ServerImpl()
{
    if (_runmode == Server::Running)
    {
        try
        {
            terminate();
        }
        catch (const std::exception& e)
        {
            log_fatal("exception in http-server termination occured: " << e.what());
        }
    }
}

void ServerImpl::listen(const std::string& ip, unsigned short int port, int backlog)
{
    log_debug("listen on " << ip << " port " << port);
    Listener* listener = new Listener(ip, port, backlog, net::TcpServer::DEFER_ACCEPT);
    try
    {
        _listener.push_back(listener);
        _queue.put(new Socket(*this, *listener));
    }
    catch (...)
    {
        delete listener;
        throw;
    }
}

void ServerImpl::start()
{
    log_trace("start server");
    runmode(Server::Starting);

    // SIGPIPE must be ignored
    ::signal(SIGPIPE, SIG_IGN);

    MutexLock lock(_threadMutex);
    while (_threads.size() < _minThreads)
    {
        Worker* worker = new Worker(*this);
        _threads.insert(worker);
        worker->start();
    }

    runmode(Server::Running);
}

void ServerImpl::terminate()
{
    log_trace("terminate");

    MutexLock lock(_threadMutex);

    runmode(Server::Terminating);

    try
    {
        log_debug("wake " << _listener.size() << " listeners");
        for (ServerImpl::ListenerType::iterator it = _listener.begin(); it != _listener.end(); ++it)
            (*it)->wakeConnect();
        _queue.put(0);

        log_debug("terminate " << _threads.size() << " threads");
        while (!_threads.empty() || !_terminatedThreads.empty())
        {
            if (!_threads.empty())
            {
                log_debug("wait for terminated thread");
                _threadTerminated.wait(lock);
            }

            for (Threads::iterator it = _terminatedThreads.begin();
                it != _terminatedThreads.end(); ++it)
            {
                log_debug("join thread");
                (*it)->join();
                delete *it;
            }

            _terminatedThreads.clear();
        }

        log_debug("delete " << _listener.size() << " listeners");
        for (ServerImpl::ListenerType::iterator it = _listener.begin(); it != _listener.end(); ++it)
            delete *it;
        _listener.clear();

        while (!_queue.empty())
            delete _queue.get();

        for (std::set<Socket*>::iterator it = _idleSockets.begin(); it != _idleSockets.end(); ++it)
            delete *it;

        runmode(Server::Stopped);
    }
    catch (const std::exception& e)
    {
        runmode(Server::Failed);
    }
}

void ServerImpl::noWaitingThreads()
{
    MutexLock lock(_threadMutex);
    if (_runmode == Server::Running)
        _eventLoop.commitEvent(NoWaitingThreadsEvent());
}

void ServerImpl::threadTerminated(Worker* worker)
{
    MutexLock lock(_threadMutex);

    _threads.erase(worker);
    if (_runmode == Server::Running)
    {
        _eventLoop.commitEvent(ThreadTerminatedEvent(worker));
    }
    else
    {
        _terminatedThreads.insert(worker);
        _threadTerminated.signal();
    }
}

void ServerImpl::addIdleSocket(Socket* socket)
{
    log_debug("add idle socket " << static_cast<void*>(socket));

    if (_runmode == Server::Running)
    {
        _eventLoop.commitEvent(IdleSocketEvent(socket));
    }
    else
    {
        log_debug("server not running; delete " << static_cast<void*>(socket));
        delete socket;
    }
}

void ServerImpl::onIdleSocket(const IdleSocketEvent& event)
{
    Socket* socket = event.socket();

    log_debug("add idle socket " << static_cast<void*>(socket) << " to selector");

    _idleSockets.insert(socket);
    socket->setSelector(&_eventLoop);
    socket->inputConnection = connect(socket->inputReady, inputSlot);
    socket->timeoutConnection = connect(socket->timeout, timeoutSlot);
}

void ServerImpl::onActiveSocket(const ActiveSocketEvent& event)
{
    _queue.put(event.socket());
}

void ServerImpl::onNoWaitingThreads(const NoWaitingThreadsEvent& event)
{
    MutexLock lock(_threadMutex);

    if (_threads.size() >= maxThreads())
    {
        log_warn("thread limit " << maxThreads() << " reached");
        return;
    }

    try
    {
        Worker* worker = new Worker(*this);
        try
        {
            log_debug("create thread " << static_cast<void*>(worker) << "; running threads=" << _threads.size());
            worker->start();
            _threads.insert(worker);

            log_debug(_threads.size() << " threads running");
        }
        catch (const std::exception&)
        {
            delete worker;
            throw;
        }
    }
    catch (const std::exception& e)
    {
        log_warn("failed to create thread: " << e.what());
    }
}

void ServerImpl::onThreadTerminated(const ThreadTerminatedEvent& event)
{
    MutexLock lock(_threadMutex);
    log_debug("thread terminated (" << static_cast<void*>(event.worker()) << ") " << _threads.size() << " threads left");
    try
    {
        event.worker()->join();
    }
    catch (const std::exception& e)
    {
        log_error("failed to join thread: " << e.what());
    }

    delete event.worker();
}

void ServerImpl::onServerStart(const ServerStartEvent& event)
{
    if (event.server() == this)
    {
        start();
    }
}

void ServerImpl::onInput(Socket& socket)
{
    socket.removeSelector();
    log_debug("search socket " << static_cast<void*>(&socket) << " in idle sockets");
    _idleSockets.erase(&socket);

    if (socket.isConnected())
    {
        socket.inputConnection.close();
        socket.timeoutConnection.close();
        _eventLoop.commitEvent(ActiveSocketEvent(&socket));
    }
    else
    {
        log_debug("onInput; delete " << static_cast<void*>(&socket));
        delete &socket;
    }
}

void ServerImpl::onTimeout(Socket& socket)
{
    log_debug("timeout; socket " << static_cast<void*>(&socket));

    _eventLoop.commitEvent(KeepAliveTimeoutEvent(&socket));
}

void ServerImpl::onKeepAliveTimeout(const KeepAliveTimeoutEvent& event)
{
    Socket* socket = event.socket();
    _idleSockets.erase(socket);
    log_debug("onKeepAliveTimeout; delete " << static_cast<void*>(&socket));
    delete socket;
}

}
}
<|endoftext|>


<commit_before>#include "renderer.h"
#include "pb_utils.h"
#include "gateway_mod/context.h"
#include "gateway_mod/pool.h"
#include "WS_commons/data_structures.h"

namespace navitia{

void render(webservice::RequestData& request, webservice::ResponseData& response, navitia::gateway::Context& context){
    switch(context.service){
        case navitia::gateway::Context::QUERY:
            render(request, response, *context.pb);
            break;
        case navitia::gateway::Context::BAD_RESPONSE:
            response.response << context.str;
            break;
        default:
            response.response << "<error/>";
            response.content_type = "text/xml";
    }
}

void render(webservice::RequestData& request, webservice::ResponseData& response, pbnavitia::Response& pb){
    if(request.params["format"] == "pb"){
        pb.SerializeToOstream(&response.response);
        response.content_type = "application/octet-stream";
    }else if(request.params["format"] == "xml"){
        response.response << pb2xml(&pb);
        response.content_type = "text/xml";
    }else{
        response.response << pb2json(&pb, 0);
        response.content_type = "text/json";
    }
}

//on recopie le pool, de cette facon le vecteur de pointeur n'est pas modifié pendant l'execution
void render_status(webservice::RequestData&, webservice::ResponseData& response, navitia::gateway::Context&, navitia::gateway::Pool pool){
    response.response << "<GatewayStatus><NavitiaList Count=\"" << pool.navitia_list.size() << "\">";
    BOOST_FOREACH(auto nav, pool.navitia_list){
        response.response << "<Navitia unusedThread=\"" << nav->unused_thread << "\" currentRequest=\"";
        response.response << nav->current_thread <<  "\">" << nav->url << "</Navitia>";
    }
    response.response << "</NavitiaList></GatewayStatus>";
    response.content_type = "text/xml";
}

}
<commit_msg>changement du cntent type pour json<commit_after>#include "renderer.h"
#include "pb_utils.h"
#include "gateway_mod/context.h"
#include "gateway_mod/pool.h"
#include "WS_commons/data_structures.h"

namespace navitia{

void render(webservice::RequestData& request, webservice::ResponseData& response, navitia::gateway::Context& context){
    switch(context.service){
        case navitia::gateway::Context::QUERY:
            render(request, response, *context.pb);
            break;
        case navitia::gateway::Context::BAD_RESPONSE:
            response.response << context.str;
            break;
        default:
            response.response << "<error/>";
            response.content_type = "text/xml";
    }
}

void render(webservice::RequestData& request, webservice::ResponseData& response, pbnavitia::Response& pb){
    if(request.params["format"] == "pb"){
        pb.SerializeToOstream(&response.response);
        response.content_type = "application/octet-stream";
    }else if(request.params["format"] == "xml"){
        response.response << pb2xml(&pb);
        response.content_type = "text/xml";
    }else{
        response.response << pb2json(&pb, 0);
        response.content_type = "application/json";
    }
}

//on recopie le pool, de cette facon le vecteur de pointeur n'est pas modifié pendant l'execution
void render_status(webservice::RequestData&, webservice::ResponseData& response, navitia::gateway::Context&, navitia::gateway::Pool pool){
    response.response << "<GatewayStatus><NavitiaList Count=\"" << pool.navitia_list.size() << "\">";
    BOOST_FOREACH(auto nav, pool.navitia_list){
        response.response << "<Navitia unusedThread=\"" << nav->unused_thread << "\" currentRequest=\"";
        response.response << nav->current_thread <<  "\">" << nav->url << "</Navitia>";
    }
    response.response << "</NavitiaList></GatewayStatus>";
    response.content_type = "text/xml";
}

}
<|endoftext|>


<commit_before>#include "Unpacker.h"

#include "ofUtils.h"

using namespace std;

namespace ofxMessagePack {
	//----------
	Unpacker::Unpacker() {
		this->hasMessageReady = false;
	}

	//----------
	bool Unpacker::load(string filename) {
		ifstream file;
		file.open(ofToDataPath(filename).c_str(), ios::in | ios::binary);
		try {
			if (file.fail()) {
				return false;
			}
			ofBuffer buffer(file);
			file.close();
			this->setBuffer(buffer);
			return true;
		} catch (std::exception & e) {
			ofLogError("ofxMessagePack") << "Failed to save to file \"" << filename << " : " << e.what();
			file.close();
			return false;
		}
	}

	//----------
	bool Unpacker::isMessageReady() const {
		return this->hasMessageReady;
	}

	//----------
	ofBuffer Unpacker::getBuffer() const {
		ofBuffer buffer;

		//msgpack-c should have both const and non-const accessors
		auto & constUnpacker = const_cast<msgpack::unpacker &>(this->unpacker);

		buffer.set(constUnpacker.buffer(), this->unpacker.buffer_capacity());

		return buffer;
	}

	//----------
	void Unpacker::setBuffer(const ofBuffer & buffer) {
		this->unpacker.reserve_buffer(buffer.size());
		memcpy(unpacker.buffer(), buffer.getBinaryBuffer(), buffer.size());
		this->unpacker.buffer_consumed(buffer.size());
		this->moveToNextMessage();
	}

	//----------
	void Unpacker::moveToNextMessage() {
		if (this->unpacker.next(this->message)) {
			this->hasMessageReady = true;
		} else {
			this->hasMessageReady = false;
		}
	}
}
<commit_msg>getBinaryBuffer -> getData<commit_after>#include "Unpacker.h"

#include "ofUtils.h"

using namespace std;

namespace ofxMessagePack {
	//----------
	Unpacker::Unpacker() {
		this->hasMessageReady = false;
	}

	//----------
	bool Unpacker::load(string filename) {
		ifstream file;
		file.open(ofToDataPath(filename).c_str(), ios::in | ios::binary);
		try {
			if (file.fail()) {
				return false;
			}
			ofBuffer buffer(file);
			file.close();
			this->setBuffer(buffer);
			return true;
		} catch (std::exception & e) {
			ofLogError("ofxMessagePack") << "Failed to save to file \"" << filename << " : " << e.what();
			file.close();
			return false;
		}
	}

	//----------
	bool Unpacker::isMessageReady() const {
		return this->hasMessageReady;
	}

	//----------
	ofBuffer Unpacker::getBuffer() const {
		ofBuffer buffer;

		//msgpack-c should have both const and non-const accessors
		auto & constUnpacker = const_cast<msgpack::unpacker &>(this->unpacker);

		buffer.set(constUnpacker.buffer(), this->unpacker.buffer_capacity());

		return buffer;
	}

	//----------
	void Unpacker::setBuffer(const ofBuffer & buffer) {
		this->unpacker.reserve_buffer(buffer.size());
		memcpy(unpacker.buffer(), buffer.getData(), buffer.size());
		this->unpacker.buffer_consumed(buffer.size());
		this->moveToNextMessage();
	}

	//----------
	void Unpacker::moveToNextMessage() {
		if (this->unpacker.next(this->message)) {
			this->hasMessageReady = true;
		} else {
			this->hasMessageReady = false;
		}
	}
}
<|endoftext|>


<commit_before>#include "cfg.h"
#include "hg.h"
#include "cfg_format.h"
#include "cfg_binarize.h"

using namespace std;

void CFG::Binarize(CFGBinarize const& b) {
  if (!b.Binarizing()) return;
  if (!b.bin_l2r) {
    assert(b.bin_l2r);
    return;
  }
  // l2r only so far:
  cerr << "Binarizing "<<b<<endl;
  //TODO.
}

void CFG::Init(Hypergraph const& hg,bool target_side,bool copy_features,bool push_weights) {
  uninit=false;
  hg_=&hg;
  Hypergraph::NodeProbs np;
  goal_inside=hg.ComputeNodeViterbi(&np);
  pushed_inside=push_weights ? goal_inside : prob_t(1);
  int nn=hg.nodes_.size(),ne=hg.edges_.size();
  nts.resize(nn);
  goal_nt=nn-1;
  rules.resize(ne);
  for (int i=0;i<nn;++i) {
    nts[i].ruleids=hg.nodes_[i].in_edges_;
    hg.SetNodeOrigin(i,nts[i].from);
  }
  for (int i=0;i<ne;++i) {
    Rule &cfgr=rules[i];
    Hypergraph::Edge const& e=hg.edges_[i];
    TRule const& er=*e.rule_; vector<WordID> const& rule_rhs=target_side?er.e():er.f();
    RHS &rhs=cfgr.rhs;
    int nr=rule_rhs.size();
    rhs.resize(nr);
    prob_t &crp=cfgr.p;
    crp=e.edge_prob_;
    cfgr.lhs=e.head_node_;
#if CFG_DEBUG
    cfgr.rule=e.rule_;
#endif
    if (copy_features) cfgr.f=e.feature_values_;
    if (push_weights) crp /=np[e.head_node_];
    for (int j=0;j<nr;++j) {
      WordID w=rule_rhs[j];
      if (w>0)
        rhs[j]=w;
      else {
        int n=e.tail_nodes_[-w];
        if (push_weights) crp*=np[n];
        rhs[j]=n;
      }
    }
  }
}

void CFG::Clear() {
  rules.clear();
  nts.clear();
  goal_nt=-1;
  hg_=0;
}

void CFG::PrintRule(std::ostream &o,RuleHandle rulei,CFGFormat const& f) const {
  Rule const& r=rules[rulei];
  f.print_lhs(o,*this,r.lhs);
  f.print_rhs(o,*this,r.rhs.begin(),r.rhs.end());
  f.print_features(o,r.p,r.f);
}

void CFG::Print(std::ostream &o,CFGFormat const& f) const {
  assert(!uninit);
  if (!f.goal_nt_name.empty()) {
    o << '['<<f.goal_nt_name <<']';
    f.print_rhs(o,*this,&goal_nt,&goal_nt+1);
    if (pushed_inside!=1)
      f.print_features(o,pushed_inside);
    o<<'\n';
  }
  for (int i=0;i<nts.size();++i) {
    Ruleids const& ntr=nts[i].ruleids;
    for (Ruleids::const_iterator j=ntr.begin(),jj=ntr.end();j!=jj;++j) {
      PrintRule(o,*j,f);
      o<<'\n';
    }
  }
}
<commit_msg>cfg print goal nt rhs<commit_after>#include "cfg.h"
#include "hg.h"
#include "cfg_format.h"
#include "cfg_binarize.h"

using namespace std;

void CFG::Binarize(CFGBinarize const& b) {
  if (!b.Binarizing()) return;
  if (!b.bin_l2r) {
    assert(b.bin_l2r);
    return;
  }
  // l2r only so far:
  cerr << "Binarizing "<<b<<endl;
  //TODO.
}

void CFG::Init(Hypergraph const& hg,bool target_side,bool copy_features,bool push_weights) {
  uninit=false;
  hg_=&hg;
  Hypergraph::NodeProbs np;
  goal_inside=hg.ComputeNodeViterbi(&np);
  pushed_inside=push_weights ? goal_inside : prob_t(1);
  int nn=hg.nodes_.size(),ne=hg.edges_.size();
  nts.resize(nn);
  goal_nt=nn-1;
  rules.resize(ne);
  for (int i=0;i<nn;++i) {
    nts[i].ruleids=hg.nodes_[i].in_edges_;
    hg.SetNodeOrigin(i,nts[i].from);
  }
  for (int i=0;i<ne;++i) {
    Rule &cfgr=rules[i];
    Hypergraph::Edge const& e=hg.edges_[i];
    TRule const& er=*e.rule_; vector<WordID> const& rule_rhs=target_side?er.e():er.f();
    RHS &rhs=cfgr.rhs;
    int nr=rule_rhs.size();
    rhs.resize(nr);
    prob_t &crp=cfgr.p;
    crp=e.edge_prob_;
    cfgr.lhs=e.head_node_;
#if CFG_DEBUG
    cfgr.rule=e.rule_;
#endif
    if (copy_features) cfgr.f=e.feature_values_;
    if (push_weights) crp /=np[e.head_node_];
    for (int j=0;j<nr;++j) {
      WordID w=rule_rhs[j];
      if (w>0)
        rhs[j]=w;
      else {
        int n=e.tail_nodes_[-w];
        if (push_weights) crp*=np[n];
        rhs[j]=n;
      }
    }
  }
}

void CFG::Clear() {
  rules.clear();
  nts.clear();
  goal_nt=-1;
  hg_=0;
}

void CFG::PrintRule(std::ostream &o,RuleHandle rulei,CFGFormat const& f) const {
  Rule const& r=rules[rulei];
  f.print_lhs(o,*this,r.lhs);
  f.print_rhs(o,*this,r.rhs.begin(),r.rhs.end());
  f.print_features(o,r.p,r.f);
}

void CFG::Print(std::ostream &o,CFGFormat const& f) const {
  assert(!uninit);
  if (!f.goal_nt_name.empty()) {
    o << '['<<f.goal_nt_name <<']';
    WordID rhs=-goal_nt;
    f.print_rhs(o,*this,&rhs,&rhs+1);
    if (pushed_inside!=1)
      f.print_features(o,pushed_inside);
    o<<'\n';
  }
  for (int i=0;i<nts.size();++i) {
    Ruleids const& ntr=nts[i].ruleids;
    for (Ruleids::const_iterator j=ntr.begin(),jj=ntr.end();j!=jj;++j) {
      PrintRule(o,*j,f);
      o<<'\n';
    }
  }
}
<|endoftext|>


<commit_before>#include "PhysicsWorld.h"
// STD
#include <array>
// bullet
#include <btBulletDynamicsCommon.h>
#include "LinearMath/btHashMap.h"
//troen
#include "../constants.h"
#include "../gamelogic.h"
#include "../util/gldebugdrawer.h"
#include "../model/abstractmodel.h"
#include "../controller/bikecontroller.h"
#include "../sound/audiomanager.h"

#include <ctime>

using namespace troen;

PhysicsWorld::PhysicsWorld(
	std::shared_ptr<GameLogic>& gameLogic,
	bool useDebugView) :
m_lastSimulationTime(0),
m_useDebugView(useDebugView),
m_gameLogic(gameLogic)
{
	initializeWorld();

	if (m_useDebugView)
	{
		m_debug = new util::GLDebugDrawer();
		m_debug->setDebugMode(btIDebugDraw::DBG_MAX_DEBUG_DRAW_MODE);
		m_world->setDebugDrawer(m_debug);
	}
}

std::array<std::array<int, 100>, 100>* PhysicsWorld::discretizeWorld()
{
	const float halfedLevelSize = LEVEL_SIZE / 2;
	const float discreteLevelSize = 100;
	const float steps = LEVEL_SIZE / discreteLevelSize;

	//return &m_discretizedWorld;
	clock_t start, end;
	start = std::clock();

	//for (int yeah = 0; yeah < 1000; yeah++) {

		// clear

	for (int x = 0; x < discreteLevelSize; x++) {
		for (int y = 0; y < discreteLevelSize; y++) {
			std::cout << " " << m_discretizedWorld[y][x];
			m_discretizedWorld[y][x] = 0;

		}
		std::cout << std::endl;
	}

	std::cout << std::endl;

	// fill

	btVector3 from, to, direction;
	btCollisionWorld::AllHitsRayResultCallback RayCallback(from, to);

	float y, x;

	from.setY(-halfedLevelSize);
	to.setY(+halfedLevelSize);
	from.setZ(1.1);
	to.setZ(1.1);

	for (x = -LEVEL_SIZE / 2; x < LEVEL_SIZE / 2; x += steps) {
		from.setX(x);
		to.setX(x);

		m_world->rayTest(from, to, RayCallback);
		if (RayCallback.hasHit()) {
			btAlignedObjectArray<btVector3> collisionPoints = RayCallback.m_hitPointWorld;

			for (int index = 0; index < collisionPoints.size(); index++) {
				btVector3 position = collisionPoints.at(index);

				if (abs(position.x()) > halfedLevelSize || abs(position.y()) > halfedLevelSize) {
					std::cout << "weird answer of bullet" << position << std::endl;
				}
				else {

					int hitY = (position.y() + halfedLevelSize) / steps;
					int hitX = (x + halfedLevelSize) / steps;

					if (hitY < 0 || hitX < 0 || hitY >= discreteLevelSize || hitX >= discreteLevelSize) {
						std::cout << "hitY: " << hitY << " hitX: " << hitX << std::endl;
					}
					else
					{
						m_discretizedWorld[hitY][hitX] = 1;
					}
				}
			}
		}
	}

	from.setX(-halfedLevelSize);
	to.setX(+halfedLevelSize);
	from.setZ(1.1);
	to.setZ(1.1);

	for (y = -LEVEL_SIZE / 2; y < LEVEL_SIZE / 2; y += steps) {
		from.setY(y);
		to.setY(y);

		m_world->rayTest(from, to, RayCallback);
		if (RayCallback.hasHit()) {
			btAlignedObjectArray<btVector3> collisionPoints = RayCallback.m_hitPointWorld;

			for (int index = 0; index < collisionPoints.size(); index++) {
				btVector3 position = collisionPoints.at(index);

				if (abs(position.x()) > halfedLevelSize || abs(position.y()) > halfedLevelSize) {
					std::cout << "weird answer of bullet" << position << std::endl;
				} else {

					int hitX = (position.x() + halfedLevelSize) / steps;
					int hitY = (y + halfedLevelSize) / steps;
					if (hitY < 0 || hitX < 0 || hitY >= discreteLevelSize || hitX >= discreteLevelSize) {
						std::cout << "hitY: " << hitY << " hitX: " << hitX << std::endl;
					}
					else {
						m_discretizedWorld[hitY][hitX] = 1;
					}
				}
			}
		}
	}
	//}
	end = std::clock();
	double dif = double(end - start) / CLOCKS_PER_SEC;
	//printf("Elasped time is %.2lf seconds.", dif);

	return &m_discretizedWorld;
}

PhysicsWorld::~PhysicsWorld()
{
	delete m_world;
	delete m_solver;
	delete m_collisionConfiguration;
	delete m_dispatcher;
	delete m_broadphase;
}

void PhysicsWorld::initializeWorld()
{
	// can be used to used to filter manually potential collision partners
	m_broadphase = new btDbvtBroadphase();

	m_collisionConfiguration = new btDefaultCollisionConfiguration();
	m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);

	// potential bottleneck
	m_solver = new btSequentialImpulseConstraintSolver;

	m_world = new btDiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration);

	m_world->setGravity(DEFAULT_GRAVITY);
}

void PhysicsWorld::addRigidBodies(const std::vector<std::shared_ptr<btRigidBody>>& bodies, const short group/*=0*/, const short mask/*=0*/)
{
	for (auto body : bodies)
	{
		m_world->addRigidBody(body.get(), group, mask);
	}
}

void PhysicsWorld::addRigidBody(btRigidBody *body,const short group /*=0*/, const short mask /*=0*/)
{
	m_world->addRigidBody(body, group, mask);
}

void PhysicsWorld::removeRigidBodies(const std::vector<std::shared_ptr<btRigidBody>>& bodies)
{
	for (auto body : bodies)
		m_world->removeRigidBody(body.get());
}

void PhysicsWorld::removeRigidBody(btRigidBody* body)
{
	m_world->removeRigidBody(body);
}

void PhysicsWorld::removeCollisionObject(btCollisionObject* obj)
{
	m_world->removeCollisionObject(obj);
}

void PhysicsWorld::addCollisionObject(btCollisionObject* obj)
{
	m_world->addCollisionObject(obj);
}

void PhysicsWorld::stepSimulation(long double currentTime)
{
	float timeSinceLastSimulation = currentTime - m_lastSimulationTime;
	m_lastSimulationTime = currentTime;

	// careful:
	// including this debug-printout will significantly reduce
	// framerate & flow of the game
	//std::cout << "[PhysicsWorld::stepSimulation] timeSinceLastSimulation = " << timeSinceLastSimulation/1000 << std::endl;

	if (m_useDebugView)
	{
		m_debug->BeginDraw();
	}

	// mind the following constraint:
	// timeStep < maxSubSteps * fixedTimeStep
	// where the parameters are given as follows:
	// stepSimulation(timeStep, maxSubSteps, fixedTimeStep)
	m_world->stepSimulation(timeSinceLastSimulation/1000.f, 8);

	if (m_useDebugView)
	{
		m_world->debugDrawWorld();
		m_debug->EndDraw();
	}

	checkForCollisionEvents();

	discretizeWorld();

}

void PhysicsWorld::checkForCollisionEvents()
{
	// keep a list of the collision pairs we
	// found during the current update
	CollisionPairSet pairsThisUpdate;

	// iterate through all of the manifolds in the dispatcher
	for (int i = 0; i < m_dispatcher->getNumManifolds(); ++i) {

		// get the manifold
		btPersistentManifold* contactManifold = m_dispatcher->getManifoldByIndexInternal(i);

		// ignore manifolds that have no contact points.
		if (contactManifold->getNumContacts() > 0)
		{
			// get the two rigid bodies involved in the collision
			const btRigidBody* pBody0 = static_cast<const btRigidBody*>(contactManifold->getBody0());
			const btRigidBody* pBody1 = static_cast<const btRigidBody*>(contactManifold->getBody1());

			// create the pair in a predictable order (using the pointer value)
			bool const swapped = pBody0 > pBody1;
			const btRigidBody* pSortedBodyA = swapped ? pBody1 : pBody0;
			const btRigidBody* pSortedBodyB = swapped ? pBody0 : pBody1;

			// create the pair
			CollisionPair thisPair = std::make_pair(pSortedBodyA, pSortedBodyB);

			// insert the pair into the current list
			pairsThisUpdate.insert(thisPair);

			// if this pair doesn't exist in the list
			// from the previous update, it is a new
			// pair and we must send a collision event
			if (m_pairsLastUpdate.find(thisPair) == m_pairsLastUpdate.end())
					m_gameLogic.lock()->collisionEvent((btRigidBody*)pBody0, (btRigidBody*)pBody1, contactManifold);
		}
	}

	// create another list for pairs that were removed this update
	CollisionPairSet removedPairs;

	// get the difference between collision pairs from the last update,
	// and this update and pushes them into the removed pairs list
	std::set_difference(m_pairsLastUpdate.begin(), m_pairsLastUpdate.end(),
		pairsThisUpdate.begin(), pairsThisUpdate.end(),
		std::inserter(removedPairs, removedPairs.begin()));

	// iterate through all of the removed pairs sending separation events for them
	for (CollisionPairSet::const_iterator iter = removedPairs.begin(); iter != removedPairs.end(); ++iter)
		m_gameLogic.lock()->separationEvent((btRigidBody*)iter->first, (btRigidBody*)iter->second);

	// in the next iteration we'll want to compare against
	// the pairs we found in this iteration
	m_pairsLastUpdate = pairsThisUpdate;
}

<commit_msg>#62 temporary commit<commit_after>#include "PhysicsWorld.h"
// STD
#include <array>
// bullet
#include <btBulletDynamicsCommon.h>
#include "LinearMath/btHashMap.h"
//troen
#include "../constants.h"
#include "../gamelogic.h"
#include "../util/gldebugdrawer.h"
#include "../model/abstractmodel.h"
#include "../controller/bikecontroller.h"
#include "../sound/audiomanager.h"

#include <ctime>

using namespace troen;

PhysicsWorld::PhysicsWorld(
	std::shared_ptr<GameLogic>& gameLogic,
	bool useDebugView) :
m_lastSimulationTime(0),
m_useDebugView(useDebugView),
m_gameLogic(gameLogic)
{
	initializeWorld();

	if (m_useDebugView)
	{
		m_debug = new util::GLDebugDrawer();
		m_debug->setDebugMode(btIDebugDraw::DBG_MAX_DEBUG_DRAW_MODE);
		m_world->setDebugDrawer(m_debug);
	}
}

std::array<std::array<int, 100>, 100>* PhysicsWorld::discretizeWorld()
{
	const float halfedLevelSize = LEVEL_SIZE / 2;
	const float discreteLevelSize = 100;
	const float stepSize = LEVEL_SIZE / discreteLevelSize;
	return &m_discretizedWorld;
	// print && clear

	for (int x = 0; x < discreteLevelSize; x++) {
		for (int y = 0; y < discreteLevelSize; y++) {
			std::cout << " " << m_discretizedWorld[y][x];
			m_discretizedWorld[y][x] = 0;

		}
		std::cout << std::endl;
	}
	std::cout << std::endl;

	btCollisionObjectArray objects = m_world->getCollisionObjectArray();
	for (size_t i = 0; i < objects.size(); i++)
	{
		btCollisionObject* object = objects[i];
		btTransform pos = object->getWorldTransform();
		pos.getOrigin();
		btCollisionShape* shape = object->getCollisionShape();
		//shape->get

	}

	// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	btVector3 from, to, direction;
	// return &m_discretizedWorld;
	clock_t start, end;
	start = std::clock();

	// clear

	for (int x = 0; x < discreteLevelSize; x++) {
		for (int y = 0; y < discreteLevelSize; y++) {
			std::cout << " " << m_discretizedWorld[y][x];
			m_discretizedWorld[y][x] = 0;

		}
		std::cout << std::endl;
	}

	std::cout << std::endl;

	// fill

	float y, x;

	from.setY(-halfedLevelSize);
	to.setY(+halfedLevelSize);
	from.setZ(1.1);
	to.setZ(1.1);

	int weirdAnswers = 0;

	for (x = -halfedLevelSize; x < halfedLevelSize; x += stepSize) {
		from.setX(x);
		to.setX(x);

		btCollisionWorld::AllHitsRayResultCallback RayCallback(from, to);
		m_world->rayTest(from, to, RayCallback);
		if (RayCallback.hasHit()) {
			btAlignedObjectArray<btVector3> collisionPoints = RayCallback.m_hitPointWorld;
			std::cout << "length of collisionpoints: " << collisionPoints.size() << std::endl;
			for (int index = 0; index < collisionPoints.size(); index++) {
				btVector3 position = collisionPoints.at(index);

				if (false && (abs(position.x()) > halfedLevelSize || abs(position.y()) != halfedLevelSize)) {
					std::cout << "weird answer of bullet" << position.x() << "  " << position.y() << "  " << position.z() << std::endl;
					weirdAnswers++;
				}
				else {

					int hitY = (position.y() + halfedLevelSize) / stepSize;
					int hitX = (x + halfedLevelSize) / stepSize;

					if (hitY < 0 || hitX < 0 || hitY >= discreteLevelSize || hitX >= discreteLevelSize) {
						std::cout << "hitY: " << hitY << " hitX: " << hitX << std::endl;
					}
					else
					{
						m_discretizedWorld[hitY][hitX] = 1;
					}
				}
			}
		}
	}

	from.setX(-halfedLevelSize);
	to.setX(+halfedLevelSize);
	from.setZ(1.1);
	to.setZ(1.1);

	for (y = -LEVEL_SIZE / 2; y < LEVEL_SIZE / 2; y += stepSize) {
		from.setY(y);
		to.setY(y);

		btVector3 from, to, direction;
		btCollisionWorld::AllHitsRayResultCallback RayCallback(from, to);
		m_world->rayTest(from, to, RayCallback);
		if (RayCallback.hasHit()) {
			btAlignedObjectArray<btVector3> collisionPoints = RayCallback.m_hitPointWorld;
			std::cout << "length of collisionpoints: " << collisionPoints.size() << std::endl;

			for (int index = 0; index < collisionPoints.size(); index++) {
				btVector3 position = collisionPoints.at(index);

				if (false && (abs(position.y()) > halfedLevelSize || abs(position.x()) != halfedLevelSize)) {
					std::cout << "weird answer of bullet" << position.x() << "  " << position.y() << "  " << position.z() << std::endl << std::endl;
					weirdAnswers++;
				} else {

					int hitX = (position.x() + halfedLevelSize) / stepSize;
					int hitY = (y + halfedLevelSize) / stepSize;
					if (hitY < 0 || hitX < 0 || hitY >= discreteLevelSize || hitX >= discreteLevelSize) {
						std::cout << "hitY: " << hitY << " hitX: " << position.x() << "  " << position.y() << "  " << position.z() << std::endl;
					}
					else {
						m_discretizedWorld[hitY][hitX] = 1;
					}
				}
			}
		}
	}
	//}
	end = std::clock();
	double dif = double(end - start) / CLOCKS_PER_SEC;
	//printf("Elasped time is %.2lf seconds.", dif);

	std::cout << "weird answers in total: " << weirdAnswers << std::endl;

	return &m_discretizedWorld;
}

PhysicsWorld::~PhysicsWorld()
{
	delete m_world;
	delete m_solver;
	delete m_collisionConfiguration;
	delete m_dispatcher;
	delete m_broadphase;
}

void PhysicsWorld::initializeWorld()
{
	// can be used to used to filter manually potential collision partners
	m_broadphase = new btDbvtBroadphase();

	m_collisionConfiguration = new btDefaultCollisionConfiguration();
	m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);

	// potential bottleneck
	m_solver = new btSequentialImpulseConstraintSolver;

	m_world = new btDiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration);

	m_world->setGravity(DEFAULT_GRAVITY);
}

void PhysicsWorld::addRigidBodies(const std::vector<std::shared_ptr<btRigidBody>>& bodies, const short group/*=0*/, const short mask/*=0*/)
{
	for (auto body : bodies)
	{
		m_world->addRigidBody(body.get(), group, mask);
	}
}

void PhysicsWorld::addRigidBody(btRigidBody *body,const short group /*=0*/, const short mask /*=0*/)
{
	m_world->addRigidBody(body, group, mask);
}

void PhysicsWorld::removeRigidBodies(const std::vector<std::shared_ptr<btRigidBody>>& bodies)
{
	for (auto body : bodies)
		m_world->removeRigidBody(body.get());
}

void PhysicsWorld::removeRigidBody(btRigidBody* body)
{
	m_world->removeRigidBody(body);
}

void PhysicsWorld::removeCollisionObject(btCollisionObject* obj)
{
	m_world->removeCollisionObject(obj);
}

void PhysicsWorld::addCollisionObject(btCollisionObject* obj)
{
	m_world->addCollisionObject(obj);
}

void PhysicsWorld::stepSimulation(long double currentTime)
{
	float timeSinceLastSimulation = currentTime - m_lastSimulationTime;
	m_lastSimulationTime = currentTime;

	// careful:
	// including this debug-printout will significantly reduce
	// framerate & flow of the game
	//std::cout << "[PhysicsWorld::stepSimulation] timeSinceLastSimulation = " << timeSinceLastSimulation/1000 << std::endl;

	if (m_useDebugView)
	{
		m_debug->BeginDraw();
	}

	// mind the following constraint:
	// timeStep < maxSubSteps * fixedTimeStep
	// where the parameters are given as follows:
	// stepSimulation(timeStep, maxSubSteps, fixedTimeStep)
	m_world->stepSimulation(timeSinceLastSimulation/1000.f, 8);

	if (m_useDebugView)
	{
		m_world->debugDrawWorld();
		m_debug->EndDraw();
	}

	checkForCollisionEvents();

	discretizeWorld();

}

void PhysicsWorld::checkForCollisionEvents()
{
	// keep a list of the collision pairs we
	// found during the current update
	CollisionPairSet pairsThisUpdate;

	// iterate through all of the manifolds in the dispatcher
	for (int i = 0; i < m_dispatcher->getNumManifolds(); ++i) {

		// get the manifold
		btPersistentManifold* contactManifold = m_dispatcher->getManifoldByIndexInternal(i);

		// ignore manifolds that have no contact points.
		if (contactManifold->getNumContacts() > 0)
		{
			// get the two rigid bodies involved in the collision
			const btRigidBody* pBody0 = static_cast<const btRigidBody*>(contactManifold->getBody0());
			const btRigidBody* pBody1 = static_cast<const btRigidBody*>(contactManifold->getBody1());

			// create the pair in a predictable order (using the pointer value)
			bool const swapped = pBody0 > pBody1;
			const btRigidBody* pSortedBodyA = swapped ? pBody1 : pBody0;
			const btRigidBody* pSortedBodyB = swapped ? pBody0 : pBody1;

			// create the pair
			CollisionPair thisPair = std::make_pair(pSortedBodyA, pSortedBodyB);

			// insert the pair into the current list
			pairsThisUpdate.insert(thisPair);

			// if this pair doesn't exist in the list
			// from the previous update, it is a new
			// pair and we must send a collision event
			if (m_pairsLastUpdate.find(thisPair) == m_pairsLastUpdate.end())
					m_gameLogic.lock()->collisionEvent((btRigidBody*)pBody0, (btRigidBody*)pBody1, contactManifold);
		}
	}

	// create another list for pairs that were removed this update
	CollisionPairSet removedPairs;

	// get the difference between collision pairs from the last update,
	// and this update and pushes them into the removed pairs list
	std::set_difference(m_pairsLastUpdate.begin(), m_pairsLastUpdate.end(),
		pairsThisUpdate.begin(), pairsThisUpdate.end(),
		std::inserter(removedPairs, removedPairs.begin()));

	// iterate through all of the removed pairs sending separation events for them
	for (CollisionPairSet::const_iterator iter = removedPairs.begin(); iter != removedPairs.end(); ++iter)
		m_gameLogic.lock()->separationEvent((btRigidBody*)iter->first, (btRigidBody*)iter->second);

	// in the next iteration we'll want to compare against
	// the pairs we found in this iteration
	m_pairsLastUpdate = pairsThisUpdate;
}

<|endoftext|>


<commit_before>#ifndef MURMUR_HASH_H
#define MURMUR_HASH_H

#include <stdint.h>

uint64_t MurmurHash64A ( const void * key, int len, unsigned int seed ) {
    const uint64_t m = 0xc6a4a7935bd1e995;
    const int r = 47;

    uint64_t h = seed ^ (len * m);

    const uint64_t * data = (const uint64_t *)key;
    const uint64_t * end = data + (len/8);

    while (data != end)
    {
        uint64_t k = *data++;

        k *= m;
        k ^= k >> r;
        k *= m;

        h ^= k;
        h *= m;
    }

    const unsigned char * data2 = (const unsigned char*)data;

    switch(len & 7)
    {
    case 7:
        h ^= uint64_t(data2[6]) << 48;
    case 6:
        h ^= uint64_t(data2[5]) << 40;
    case 5:
        h ^= uint64_t(data2[4]) << 32;
    case 4:
        h ^= uint64_t(data2[3]) << 24;
    case 3:
        h ^= uint64_t(data2[2]) << 16;
    case 2:
        h ^= uint64_t(data2[1]) << 8;
    case 1:
        h ^= uint64_t(data2[0]);
        h *= m;
    };

    h ^= h >> r;
    h *= m;
    h ^= h >> r;

    return h;
}

#endif
<commit_msg>Update murmur.hpp<commit_after>#ifndef MURMUR_HASH_H
#define MURMUR_HASH_H

#include <stdint.h>

//-----------------------------------------------------------------------------
// MurmurHash2, 64-bit versions, by Austin Appleby

// The same caveats as 32-bit MurmurHash2 apply here - beware of alignment
// and endian-ness issues if used across multiple platforms.

// 64-bit hash for 64-bit platforms

uint64_t MurmurHash64A ( const void * key, int len, unsigned int seed ) {
    const uint64_t m = 0xc6a4a7935bd1e995;
    const int r = 47;

    uint64_t h = seed ^ (len * m);

    const uint64_t * data = (const uint64_t *)key;
    const uint64_t * end = data + (len/8);

    while (data != end)
    {
        uint64_t k = *data++;

        k *= m;
        k ^= k >> r;
        k *= m;

        h ^= k;
        h *= m;
    }

    const unsigned char * data2 = (const unsigned char*)data;

    switch(len & 7)
    {
    case 7:
        h ^= uint64_t(data2[6]) << 48;
    case 6:
        h ^= uint64_t(data2[5]) << 40;
    case 5:
        h ^= uint64_t(data2[4]) << 32;
    case 4:
        h ^= uint64_t(data2[3]) << 24;
    case 3:
        h ^= uint64_t(data2[2]) << 16;
    case 2:
        h ^= uint64_t(data2[1]) << 8;
    case 1:
        h ^= uint64_t(data2[0]);
        h *= m;
    };

    h ^= h >> r;
    h *= m;
    h ^= h >> r;

    return h;
}

#endif
<|endoftext|>


<commit_before>#include <plasp/sas/TranslatorASP.h>

#include <plasp/utils/Formatting.h>

namespace plasp
{
namespace sas
{

////////////////////////////////////////////////////////////////////////////////////////////////////
//
// TranslatorASP
//
////////////////////////////////////////////////////////////////////////////////////////////////////

TranslatorASP::TranslatorASP(const Description &description, utils::LogStream &ostream)
:	m_description(description),
	m_outputStream(ostream)
{
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void TranslatorASP::translate() const
{
	// TODO: remove double computation of requirements
	if (m_description.hasRequirements())
	{
		translateRequirements();
		m_outputStream << std::endl;
	}

	translateVariables();
	m_outputStream << std::endl;
	translateActions();
	m_outputStream << std::endl;
	translateMutexes();

	if (m_description.usesAxiomRules())
	{
		m_outputStream << std::endl;
		translateAxiomRules();
	}

	m_outputStream << std::endl;
	translateInitialState();
	m_outputStream << std::endl;
	translateGoal();
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void TranslatorASP::translateRequirements() const
{
	m_outputStream << utils::Heading2("feature requirements") << std::endl;

	if (m_description.usesActionCosts())
		m_outputStream << utils::Keyword("requires") << "(" << utils::Keyword("feature") << "(actionCosts))." << std::endl;

	if (m_description.usesAxiomRules())
		m_outputStream << utils::Keyword("requires") << "(" << utils::Keyword("feature") << "(axiomRules))." << std::endl;

	if (m_description.usesConditionalEffects())
		m_outputStream << utils::Keyword("requires") << "(" << utils::Keyword("feature") << "(conditionalEffects))." << std::endl;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void TranslatorASP::translateInitialState() const
{
	m_outputStream << utils::Heading2("initial state") << std::endl;

	const auto &initialStateFacts = m_description.initialState().facts();

	std::for_each(initialStateFacts.cbegin(), initialStateFacts.cend(),
		[&](const auto &fact)
		{
			m_outputStream << utils::Keyword("initialState") << "(";
			fact.variable().printNameAsASPPredicate(m_outputStream);
			m_outputStream << ", ";
			fact.value().printAsASPPredicate(m_outputStream);
			m_outputStream << ")." << std::endl;
		});
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void TranslatorASP::translateGoal() const
{
	m_outputStream << utils::Heading2("goal") << std::endl;

	const auto &goalFacts = m_description.goal().facts();

	std::for_each(goalFacts.cbegin(), goalFacts.cend(),
		[&](const auto &fact)
		{
			m_outputStream << utils::Keyword("goal") << "(";
			fact.variable().printNameAsASPPredicate(m_outputStream);
			m_outputStream << ", ";
			fact.value().printAsASPPredicate(m_outputStream);
			m_outputStream << ")." << std::endl;
		});
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void TranslatorASP::translateVariables() const
{
	m_outputStream << utils::Heading2("variables");

	const auto &variables = m_description.variables();

	std::for_each(variables.cbegin(), variables.cend(),
		[&](const auto &variable)
		{
			const auto &values = variable.values();

			BOOST_ASSERT(!values.empty());

			m_outputStream << std::endl << utils::Keyword("variable") << "(";
			variable.printNameAsASPPredicate(m_outputStream);
			m_outputStream << ")." << std::endl;

			std::for_each(values.cbegin(), values.cend(),
				[&](const auto &value)
				{
					m_outputStream << utils::Keyword("contains") << "(";
					variable.printNameAsASPPredicate(m_outputStream);
					m_outputStream << ", ";
					value.printAsASPPredicate(m_outputStream);
					m_outputStream << ")." << std::endl;
				});
		});
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void TranslatorASP::translateActions() const
{
	m_outputStream << utils::Heading2("actions");

	const auto &operators = m_description.operators();

	std::for_each(operators.cbegin(), operators.cend(),
		[&](const auto &operator_)
		{
			m_outputStream << std::endl << utils::Keyword("action") << "(";
			operator_.printPredicateAsASP(m_outputStream);
			m_outputStream << ")." << std::endl;

			const auto &preconditions = operator_.preconditions();

			std::for_each(preconditions.cbegin(), preconditions.cend(),
				[&](const auto &precondition)
				{
					m_outputStream << utils::Keyword("precondition") << "(";
					operator_.printPredicateAsASP(m_outputStream);
					m_outputStream << ", ";
					precondition.variable().printNameAsASPPredicate(m_outputStream);
					m_outputStream << ", ";
					precondition.value().printAsASPPredicate(m_outputStream);
					m_outputStream << ")." << std::endl;
				});

			const auto &effects = operator_.effects();

			size_t currentEffectID = 0;

			std::for_each(effects.cbegin(), effects.cend(),
				[&](const auto &effect)
				{
					const auto &conditions = effect.conditions();

					std::for_each(conditions.cbegin(), conditions.cend(),
						[&](const auto &condition)
						{
							m_outputStream << utils::Keyword("effectCondition") << "(";
							operator_.printPredicateAsASP(m_outputStream);
							m_outputStream << ", " << utils::Keyword("effect") << "(" << utils::Number(std::to_string(currentEffectID)) << "), ";
							condition.variable().printNameAsASPPredicate(m_outputStream);
							m_outputStream << ", ";
							condition.value().printAsASPPredicate(m_outputStream);
							m_outputStream << ")." << std::endl;
						});

					m_outputStream << utils::Keyword("postcondition") << "(";
					operator_.printPredicateAsASP(m_outputStream);
					m_outputStream << ", " << utils::Keyword("effect") << "(" << utils::Number(std::to_string(currentEffectID)) << "), ";
					effect.postcondition().variable().printNameAsASPPredicate(m_outputStream);
					m_outputStream << ", ";
					effect.postcondition().value().printAsASPPredicate(m_outputStream);
					m_outputStream << ")." << std::endl;

					currentEffectID++;
				});

			m_outputStream << utils::Keyword("costs") << "(";
			operator_.printPredicateAsASP(m_outputStream);
			m_outputStream << ", " << operator_.costs() << ")." << std::endl;
		});
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void TranslatorASP::translateMutexes() const
{
	m_outputStream << utils::Heading2("mutex groups");

	const auto &mutexGroups = m_description.mutexGroups();

	size_t currentMutexGroupID = 0;

	std::for_each(mutexGroups.cbegin(), mutexGroups.cend(),
		[&](const auto &mutexGroup)
		{
			const auto mutexGroupID = std::to_string(currentMutexGroupID);
			currentMutexGroupID++;

			m_outputStream
				<< std::endl
				<< utils::Keyword("mutexGroup") << "("
				<< utils::Keyword("mutexGroup") << "("
				<< utils::Number(mutexGroupID)
				<< "))." << std::endl;

			const auto &facts = mutexGroup.facts();

			std::for_each(facts.cbegin(), facts.cend(),
				[&](const auto &fact)
				{
					m_outputStream << utils::Keyword("contains") << "(" << utils::Keyword("mutexGroup") << "(" << utils::Number(mutexGroupID) << "), ";
					fact.variable().printNameAsASPPredicate(m_outputStream);
					m_outputStream << ", ";
					fact.value().printAsASPPredicate(m_outputStream);
					m_outputStream << ")." << std::endl;
				});
		});
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void TranslatorASP::translateAxiomRules() const
{
	m_outputStream << utils::Heading2("axiom rules");

	const auto &axiomRules = m_description.axiomRules();

	size_t currentAxiomRuleID = 0;

	std::for_each(axiomRules.cbegin(), axiomRules.cend(),
		[&](const auto &axiomRule)
		{
			const auto axiomRuleID = std::to_string(currentAxiomRuleID);
			currentAxiomRuleID++;

			m_outputStream
				<< std::endl
				<< utils::Keyword("axiomRule") << "("
				<< utils::Keyword("axiomRule") << "("
				<< utils::Number(axiomRuleID)
				<< "))." << std::endl;

			const auto &conditions = axiomRule.conditions();

			std::for_each(conditions.cbegin(), conditions.cend(),
				[&](const auto &condition)
				{
					m_outputStream << utils::Keyword("condition") << "(" << utils::Keyword("axiomRule") << "(" << utils::Number(axiomRuleID) << "), ";
					condition.variable().printNameAsASPPredicate(m_outputStream);
					m_outputStream << ", ";
					condition.value().printAsASPPredicate(m_outputStream);
					m_outputStream << ")." << std::endl;
				});

			const auto &postcondition = axiomRule.postcondition();

			m_outputStream << utils::Keyword("postcondition") << "(" << utils::Keyword("axiomRule") << "(" << utils::Number(axiomRuleID) << "), ";
			postcondition.variable().printNameAsASPPredicate(m_outputStream);
			m_outputStream << ", ";
			postcondition.value().printAsASPPredicate(m_outputStream);
			m_outputStream << ")." << std::endl;
		});
}

////////////////////////////////////////////////////////////////////////////////////////////////////

}
}
<commit_msg>Changed keyword for conditions of conditional effects.<commit_after>#include <plasp/sas/TranslatorASP.h>

#include <plasp/utils/Formatting.h>

namespace plasp
{
namespace sas
{

////////////////////////////////////////////////////////////////////////////////////////////////////
//
// TranslatorASP
//
////////////////////////////////////////////////////////////////////////////////////////////////////

TranslatorASP::TranslatorASP(const Description &description, utils::LogStream &ostream)
:	m_description(description),
	m_outputStream(ostream)
{
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void TranslatorASP::translate() const
{
	// TODO: remove double computation of requirements
	if (m_description.hasRequirements())
	{
		translateRequirements();
		m_outputStream << std::endl;
	}

	translateVariables();
	m_outputStream << std::endl;
	translateActions();
	m_outputStream << std::endl;
	translateMutexes();

	if (m_description.usesAxiomRules())
	{
		m_outputStream << std::endl;
		translateAxiomRules();
	}

	m_outputStream << std::endl;
	translateInitialState();
	m_outputStream << std::endl;
	translateGoal();
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void TranslatorASP::translateRequirements() const
{
	m_outputStream << utils::Heading2("feature requirements") << std::endl;

	if (m_description.usesActionCosts())
		m_outputStream << utils::Keyword("requires") << "(" << utils::Keyword("feature") << "(actionCosts))." << std::endl;

	if (m_description.usesAxiomRules())
		m_outputStream << utils::Keyword("requires") << "(" << utils::Keyword("feature") << "(axiomRules))." << std::endl;

	if (m_description.usesConditionalEffects())
		m_outputStream << utils::Keyword("requires") << "(" << utils::Keyword("feature") << "(conditionalEffects))." << std::endl;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void TranslatorASP::translateInitialState() const
{
	m_outputStream << utils::Heading2("initial state") << std::endl;

	const auto &initialStateFacts = m_description.initialState().facts();

	std::for_each(initialStateFacts.cbegin(), initialStateFacts.cend(),
		[&](const auto &fact)
		{
			m_outputStream << utils::Keyword("initialState") << "(";
			fact.variable().printNameAsASPPredicate(m_outputStream);
			m_outputStream << ", ";
			fact.value().printAsASPPredicate(m_outputStream);
			m_outputStream << ")." << std::endl;
		});
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void TranslatorASP::translateGoal() const
{
	m_outputStream << utils::Heading2("goal") << std::endl;

	const auto &goalFacts = m_description.goal().facts();

	std::for_each(goalFacts.cbegin(), goalFacts.cend(),
		[&](const auto &fact)
		{
			m_outputStream << utils::Keyword("goal") << "(";
			fact.variable().printNameAsASPPredicate(m_outputStream);
			m_outputStream << ", ";
			fact.value().printAsASPPredicate(m_outputStream);
			m_outputStream << ")." << std::endl;
		});
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void TranslatorASP::translateVariables() const
{
	m_outputStream << utils::Heading2("variables");

	const auto &variables = m_description.variables();

	std::for_each(variables.cbegin(), variables.cend(),
		[&](const auto &variable)
		{
			const auto &values = variable.values();

			BOOST_ASSERT(!values.empty());

			m_outputStream << std::endl << utils::Keyword("variable") << "(";
			variable.printNameAsASPPredicate(m_outputStream);
			m_outputStream << ")." << std::endl;

			std::for_each(values.cbegin(), values.cend(),
				[&](const auto &value)
				{
					m_outputStream << utils::Keyword("contains") << "(";
					variable.printNameAsASPPredicate(m_outputStream);
					m_outputStream << ", ";
					value.printAsASPPredicate(m_outputStream);
					m_outputStream << ")." << std::endl;
				});
		});
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void TranslatorASP::translateActions() const
{
	m_outputStream << utils::Heading2("actions");

	const auto &operators = m_description.operators();

	std::for_each(operators.cbegin(), operators.cend(),
		[&](const auto &operator_)
		{
			m_outputStream << std::endl << utils::Keyword("action") << "(";
			operator_.printPredicateAsASP(m_outputStream);
			m_outputStream << ")." << std::endl;

			const auto &preconditions = operator_.preconditions();

			std::for_each(preconditions.cbegin(), preconditions.cend(),
				[&](const auto &precondition)
				{
					m_outputStream << utils::Keyword("precondition") << "(";
					operator_.printPredicateAsASP(m_outputStream);
					m_outputStream << ", ";
					precondition.variable().printNameAsASPPredicate(m_outputStream);
					m_outputStream << ", ";
					precondition.value().printAsASPPredicate(m_outputStream);
					m_outputStream << ")." << std::endl;
				});

			const auto &effects = operator_.effects();

			size_t currentEffectID = 0;

			std::for_each(effects.cbegin(), effects.cend(),
				[&](const auto &effect)
				{
					const auto &conditions = effect.conditions();

					std::for_each(conditions.cbegin(), conditions.cend(),
						[&](const auto &condition)
						{
							// Conditions of conditional effects
							m_outputStream << utils::Keyword("precondition") << "(";
							operator_.printPredicateAsASP(m_outputStream);
							m_outputStream << ", " << utils::Keyword("effect") << "(" << utils::Number(std::to_string(currentEffectID)) << "), ";
							condition.variable().printNameAsASPPredicate(m_outputStream);
							m_outputStream << ", ";
							condition.value().printAsASPPredicate(m_outputStream);
							m_outputStream << ")." << std::endl;
						});

					m_outputStream << utils::Keyword("postcondition") << "(";
					operator_.printPredicateAsASP(m_outputStream);
					m_outputStream << ", " << utils::Keyword("effect") << "(" << utils::Number(std::to_string(currentEffectID)) << "), ";
					effect.postcondition().variable().printNameAsASPPredicate(m_outputStream);
					m_outputStream << ", ";
					effect.postcondition().value().printAsASPPredicate(m_outputStream);
					m_outputStream << ")." << std::endl;

					currentEffectID++;
				});

			m_outputStream << utils::Keyword("costs") << "(";
			operator_.printPredicateAsASP(m_outputStream);
			m_outputStream << ", " << operator_.costs() << ")." << std::endl;
		});
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void TranslatorASP::translateMutexes() const
{
	m_outputStream << utils::Heading2("mutex groups");

	const auto &mutexGroups = m_description.mutexGroups();

	size_t currentMutexGroupID = 0;

	std::for_each(mutexGroups.cbegin(), mutexGroups.cend(),
		[&](const auto &mutexGroup)
		{
			const auto mutexGroupID = std::to_string(currentMutexGroupID);
			currentMutexGroupID++;

			m_outputStream
				<< std::endl
				<< utils::Keyword("mutexGroup") << "("
				<< utils::Keyword("mutexGroup") << "("
				<< utils::Number(mutexGroupID)
				<< "))." << std::endl;

			const auto &facts = mutexGroup.facts();

			std::for_each(facts.cbegin(), facts.cend(),
				[&](const auto &fact)
				{
					m_outputStream << utils::Keyword("contains") << "(" << utils::Keyword("mutexGroup") << "(" << utils::Number(mutexGroupID) << "), ";
					fact.variable().printNameAsASPPredicate(m_outputStream);
					m_outputStream << ", ";
					fact.value().printAsASPPredicate(m_outputStream);
					m_outputStream << ")." << std::endl;
				});
		});
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void TranslatorASP::translateAxiomRules() const
{
	m_outputStream << utils::Heading2("axiom rules");

	const auto &axiomRules = m_description.axiomRules();

	size_t currentAxiomRuleID = 0;

	std::for_each(axiomRules.cbegin(), axiomRules.cend(),
		[&](const auto &axiomRule)
		{
			const auto axiomRuleID = std::to_string(currentAxiomRuleID);
			currentAxiomRuleID++;

			m_outputStream
				<< std::endl
				<< utils::Keyword("axiomRule") << "("
				<< utils::Keyword("axiomRule") << "("
				<< utils::Number(axiomRuleID)
				<< "))." << std::endl;

			const auto &conditions = axiomRule.conditions();

			std::for_each(conditions.cbegin(), conditions.cend(),
				[&](const auto &condition)
				{
					m_outputStream << utils::Keyword("condition") << "(" << utils::Keyword("axiomRule") << "(" << utils::Number(axiomRuleID) << "), ";
					condition.variable().printNameAsASPPredicate(m_outputStream);
					m_outputStream << ", ";
					condition.value().printAsASPPredicate(m_outputStream);
					m_outputStream << ")." << std::endl;
				});

			const auto &postcondition = axiomRule.postcondition();

			m_outputStream << utils::Keyword("postcondition") << "(" << utils::Keyword("axiomRule") << "(" << utils::Number(axiomRuleID) << "), ";
			postcondition.variable().printNameAsASPPredicate(m_outputStream);
			m_outputStream << ", ";
			postcondition.value().printAsASPPredicate(m_outputStream);
			m_outputStream << ")." << std::endl;
		});
}

////////////////////////////////////////////////////////////////////////////////////////////////////

}
}
<|endoftext|>