<commit_before>// $Id: OoiEnergy_test.C,v 1.1 2000/05/30 10:28:50 oliver Exp $
#include <BALL/CONCEPT/classTest.h>

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

#include <BALL/SOLVATION/ooiEnergy.h>
#include <BALL/FORMAT/PDBFile.h>
#include <BALL/FORMAT/HINFile.h>
#include <BALL/KERNEL/system.h>
#include <BALL/STRUCTURE/fragmentDB.h>

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

START_TEST(OOiEnergy, "$Id: OoiEnergy_test.C,v 1.1 2000/05/30 10:28:50 oliver Exp $")

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

using namespace BALL;

///  insert tests for each member function here
///

PRECISION(1.0) // it's not THAT precise
CHECK(calculateOoiEnergy() / BPTI)
	System S;
	PDBFile f("data/OoiEnergy_test.pdb");
	f >> S;
	f.close();

	FragmentDB frag_db;
	S.apply(frag_db.normalize_names);
	S.apply(frag_db.build_bonds);

	TEST_EQUAL(S.countAtoms(), 892)
	float energy = calculateOoiEnergy(S);
	TEST_REAL_EQUAL(energy, -2589.7)
RESULT

CHECK(calculateOoiEnergy() / ethanol)
	System S;
	HINFile f("data/OoiEnergy_test1.hin");
	f >> S;
	f.close();

	TEST_EQUAL(S.countAtoms(), 9)
	float energy = calculateOoiEnergy(S);
	TEST_REAL_EQUAL(energy, -21.09)
	TEST_EQUAL(S.countAtoms(), 9)
	energy = calculateOoiEnergy(S);
	TEST_REAL_EQUAL(energy, -21.09)
RESULT

CHECK(calculateOoiEnergy() / acetamide)
	System S;
	HINFile f("data/OoiEnergy_test2.hin");
	f >> S;
	f.close();

	TEST_EQUAL(S.countAtoms(), 9)
	float energy = calculateOoiEnergy(S);
	TEST_REAL_EQUAL(energy, -28.04)
RESULT

CHECK(calculateOoiEnergy() / butylamine)
	System S;
	HINFile f("data/OoiEnergy_test3.hin");
	f >> S;
	f.close();

	TEST_EQUAL(S.countAtoms(), 16)
	float energy = calculateOoiEnergy(S);
	TEST_REAL_EQUAL(energy, -18.34)
RESULT

CHECK(calculateOoiEnergy() / methanethiol)
	System S;
	HINFile f("data/OoiEnergy_test4.hin");
	f >> S;
	f.close();

	TEST_EQUAL(S.countAtoms(), 6)
	float energy = calculateOoiEnergy(S);
	TEST_REAL_EQUAL(energy, -4.72)
RESULT

CHECK(calculateOoiEnergy() / acetic acid)
	System S;
	HINFile f("data/OoiEnergy_test5.hin");
	f >> S;
	f.close();

	TEST_EQUAL(S.countAtoms(), 8)
	float energy = calculateOoiEnergy(S);
	TEST_REAL_EQUAL(energy, -29.15)
RESULT

CHECK(calculateOoiEnergy() / acetate)
	System S;
	HINFile f("data/OoiEnergy_test6.hin");
	f >> S;
	f.close();

	TEST_EQUAL(S.countAtoms(), 7)
	float energy = calculateOoiEnergy(S);
	TEST_REAL_EQUAL(energy, -337.44)
RESULT

CHECK(calculateOoiEnergy() / butylammonium)
	System S;
	HINFile f("data/OoiEnergy_test7.hin");
	f >> S;
	f.close();

	TEST_EQUAL(S.countAtoms(), 17)
	float energy = calculateOoiEnergy(S);
	TEST_REAL_EQUAL(energy, -289.70)
RESULT

CHECK(calculateOoiEnergy() / propionate)
	System S;
	HINFile f("data/OoiEnergy_test8.hin");
	f >> S;
	f.close();

	TEST_EQUAL(S.countAtoms(), 10)
	float energy = calculateOoiEnergy(S);
	TEST_REAL_EQUAL(energy, -311.8)
RESULT

CHECK(calculateOoiEnergy() / methylimidazolium)
	System S;
	HINFile f("data/OoiEnergy_test9.hin");
	f >> S;
	f.close();

	TEST_EQUAL(S.countAtoms(), 13)
	float energy = calculateOoiEnergy(S);
	TEST_REAL_EQUAL(energy, -26.4)
RESULT

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
END_TEST
<commit_msg>fixed: examples were adapted to the modified parameter set<commit_after>// $Id: OoiEnergy_test.C,v 1.2 2000/05/31 17:37:07 oliver Exp $
#include <BALL/CONCEPT/classTest.h>

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

#include <BALL/SOLVATION/ooiEnergy.h>
#include <BALL/FORMAT/PDBFile.h>
#include <BALL/FORMAT/HINFile.h>
#include <BALL/KERNEL/system.h>
#include <BALL/STRUCTURE/fragmentDB.h>

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

START_TEST(OOiEnergy, "$Id: OoiEnergy_test.C,v 1.2 2000/05/31 17:37:07 oliver Exp $")

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

using namespace BALL;

///  insert tests for each member function here
///

PRECISION(1.0) // it's not THAT precise
CHECK(calculateOoiEnergy() / BPTI)
	System S;
	PDBFile f("data/OoiEnergy_test.pdb");
	f >> S;
	f.close();

	FragmentDB frag_db;
	S.apply(frag_db.normalize_names);
	S.apply(frag_db.build_bonds);

	TEST_EQUAL(S.countAtoms(), 892)
	float energy = calculateOoiEnergy(S);
	TEST_REAL_EQUAL(energy, -2602.97)
RESULT

CHECK(calculateOoiEnergy() / ethanol)
	System S;
	HINFile f("data/OoiEnergy_test1.hin");
	f >> S;
	f.close();

	TEST_EQUAL(S.countAtoms(), 9)
	float energy = calculateOoiEnergy(S);
	TEST_REAL_EQUAL(energy, -21.09)
	TEST_EQUAL(S.countAtoms(), 9)
	energy = calculateOoiEnergy(S);
	TEST_REAL_EQUAL(energy, -21.09)
RESULT

CHECK(calculateOoiEnergy() / acetamide)
	System S;
	HINFile f("data/OoiEnergy_test2.hin");
	f >> S;
	f.close();

	TEST_EQUAL(S.countAtoms(), 9)
	float energy = calculateOoiEnergy(S);
	TEST_REAL_EQUAL(energy, -28.04)
RESULT

CHECK(calculateOoiEnergy() / butylamine)
	System S;
	HINFile f("data/OoiEnergy_test3.hin");
	f >> S;
	f.close();

	TEST_EQUAL(S.countAtoms(), 16)
	float energy = calculateOoiEnergy(S);
	TEST_REAL_EQUAL(energy, -18.34)
RESULT

CHECK(calculateOoiEnergy() / methanethiol)
	System S;
	HINFile f("data/OoiEnergy_test4.hin");
	f >> S;
	f.close();

	TEST_EQUAL(S.countAtoms(), 6)
	float energy = calculateOoiEnergy(S);
	TEST_REAL_EQUAL(energy, -4.72)
RESULT

CHECK(calculateOoiEnergy() / acetic acid)
	System S;
	HINFile f("data/OoiEnergy_test5.hin");
	f >> S;
	f.close();

	TEST_EQUAL(S.countAtoms(), 8)
	float energy = calculateOoiEnergy(S);
	TEST_REAL_EQUAL(energy, -29.15)
RESULT

CHECK(calculateOoiEnergy() / acetate)
	System S;
	HINFile f("data/OoiEnergy_test6.hin");
	f >> S;
	f.close();

	TEST_EQUAL(S.countAtoms(), 7)
	float energy = calculateOoiEnergy(S);
	TEST_REAL_EQUAL(energy, -341.942)
RESULT

CHECK(calculateOoiEnergy() / butylammonium)
	System S;
	HINFile f("data/OoiEnergy_test7.hin");
	f >> S;
	f.close();

	TEST_EQUAL(S.countAtoms(), 17)
	float energy = calculateOoiEnergy(S);
	TEST_REAL_EQUAL(energy, -289.70)
RESULT

CHECK(calculateOoiEnergy() / propionate)
	System S;
	HINFile f("data/OoiEnergy_test8.hin");
	f >> S;
	f.close();

	TEST_EQUAL(S.countAtoms(), 10)
	float energy = calculateOoiEnergy(S);
	TEST_REAL_EQUAL(energy, -315.938)
RESULT

CHECK(calculateOoiEnergy() / methylimidazolium)
	System S;
	HINFile f("data/OoiEnergy_test9.hin");
	f >> S;
	f.close();

	TEST_EQUAL(S.countAtoms(), 13)
	float energy = calculateOoiEnergy(S);
	TEST_REAL_EQUAL(energy, -268.268)
RESULT

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
END_TEST
<|endoftext|>


<commit_before>#include <QCoreApplication>
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>
#include <QCache>
#include <QVector>
#include <QStringList>
#include <QSqlRecord>
#include <QUrl>
#include <QDir>
#include <cxxabi.h>
#include <QException>
#include "kernel.h"
#include "factory.h"
#include "geometries.h"
#include "connectorinterface.h"
#include "abstractfactory.h"
#include "ilwisobjectfactory.h"
#include "ilwiscontext.h"
#include "catalogconnectorfactory.h"
#include "connectorfactory.h"
#include "catalogconnector.h"
#include "featurefactory.h"
#include "georefimplementationfactory.h"
#include "catalog.h"
#include "module.h"
#include "mastercatalog.h"
#include "version.h"
#include "errorobject.h"
#include "ilwisdata.h"
#include "domain.h"
#include "domainitem.h"
#include "itemdomain.h"
#include "identifieritem.h"
#include "thematicitem.h"
#include "range.h"
#include "itemrange.h"
#include "datadefinition.h"
#include "columndefinition.h"
#include "table.h"
#include "attributerecord.h"
#include "polygon.h"
#include "geometry.h"
#include "feature.h"
#include "symboltable.h"
#include "operationmetadata.h"
#include "operationExpression.h"
#include "operation.h"
#include "commandhandler.h"

Ilwis::Kernel *Ilwis::Kernel::_kernel = 0;

using namespace Ilwis;

Catalog *createCatalog()  {
    return new Catalog();
}

Ilwis::Kernel* kernel() {
    if (Kernel::_kernel == 0) {
        Kernel::_kernel = new Kernel();
        Kernel::_kernel->init();

    }
    return Kernel::_kernel;
}

Kernel::Kernel(QObject *parent) :
    QObject(parent), _version(0)
{
}

void Kernel::init() {
    if ( !_version.isNull())
        return;

    _version.reset(new Version());
    _version->addBinaryVersion(Ilwis::Version::bvFORMAT30);
    _version->addBinaryVersion(Ilwis::Version::bvFORMATFOREIGN);
    _version->addBinaryVersion(Ilwis::Version::bvPOLYGONFORMAT37);
    _version->addODFVersion("3.1");

    _issues.reset( new IssueLogger());

    _dbPublic = QSqlDatabase::addDatabase("QSQLITE");
    _dbPublic.setHostName("localhost");
    _dbPublic.setDatabaseName(":memory:");
    _dbPublic.open();

    _dbPublic.prepare();

    CatalogConnectorFactory *catfactory = new CatalogConnectorFactory();
    addFactory(catfactory);

    ConnectorFactory *confac = new ConnectorFactory();
    addFactory(confac);

    FeatureFactory *featureFac = new FeatureFactory();
    featureFac->addCreator("feature", createFeature);
    addFactory(featureFac);

    GeoRefImplementationFactory *georefFac = new GeoRefImplementationFactory();
    georefFac->prepare();
    addFactory(georefFac);

    _modules.addModules();

    mastercatalog()->addContainer(QUrl("ilwis://system"));

   // ItemRange::addCreateItem("ThematicItem", ThematicItem::createRange());

}

Kernel::~Kernel() {
    _dbPublic.close();
    delete mastercatalog();
    delete context();

}

const QVariant *Kernel::getFromTLS(const QString& key) const{
    if (_caches.hasLocalData()) {
        return _caches.localData()->object(key);
    }
    return 0;
}

void Kernel::setTLS(const QString& key, QVariant* data){
    if (!_caches.hasLocalData())
        _caches.setLocalData(new QCache<QString, QVariant>);

    _caches.localData()->insert(key, data);
}

void Kernel::deleteTLS(const QString &key) {
    if (_caches.hasLocalData())
        _caches.localData()->remove(key);

}

QString Kernel::translate(const QString& s) const {
    //TODO implement translator class here and load in in the application object
    return s;
}

 const SPVersion& Kernel::version() const{
     return _version;
 }

PublicDatabase &Kernel::database()
{
    return _dbPublic;
}

QScopedPointer<IssueLogger>& Kernel::issues()
{
    return _issues;
}

void Kernel::addFactory(FactoryInterface *fac)
{
    QString key = fac->key().toLower();
    if (!_masterfactory.contains(key)) {
        _masterfactory[key]  = fac;
    }
}

QString Kernel::demangle(const char *mangled_name)
{
    int status;
    char *realname = abi::__cxa_demangle(mangled_name,0,0,&status);
    QString type(realname);
    free(realname);

    return type;
}

bool Kernel::error(const QString &message, const QString p1, const QString p2, const QString p3, const QString& file,  int line, const QString& func)
{
    QFileInfo inf(file);
    QString name = inf.fileName();
    quint64 issueid;
    if ( p1 == sUNDEF)
        issueid =issues()->log(TR(message));
    else if (p2 == sUNDEF)
        issueid =issues()->log(TR(message).arg(p1));
    else if ( p3 == sUNDEF)
        issueid =issues()->log(TR(message).arg(p1, p2));
    else
        issueid =issues()->log(TR(message).arg(p1).arg(p2).arg(p3));
    if ( issueid != i64UNDEF) {
        issues()->addCodeInfo(issueid, line, func, name);
    }
    return false;
}

void Kernel::startClock(){
    _start_clock = clock();
}

void Kernel::endClock(){
    clock_t end = clock();
    double total = (double)(end - _start_clock) / CLOCKS_PER_SEC;
    qDebug() << "calc old in " << total << " seconds";

}

<commit_msg>added log message for when ilwis starts and stops<commit_after>#include <QCoreApplication>
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>
#include <QCache>
#include <QVector>
#include <QStringList>
#include <QSqlRecord>
#include <QUrl>
#include <QDir>
#include <cxxabi.h>
#include <QException>
#include "kernel.h"
#include "factory.h"
#include "geometries.h"
#include "connectorinterface.h"
#include "abstractfactory.h"
#include "ilwisobjectfactory.h"
#include "ilwiscontext.h"
#include "catalogconnectorfactory.h"
#include "connectorfactory.h"
#include "catalogconnector.h"
#include "featurefactory.h"
#include "georefimplementationfactory.h"
#include "catalog.h"
#include "module.h"
#include "mastercatalog.h"
#include "version.h"
#include "errorobject.h"
#include "ilwisdata.h"
#include "domain.h"
#include "domainitem.h"
#include "itemdomain.h"
#include "identifieritem.h"
#include "thematicitem.h"
#include "range.h"
#include "itemrange.h"
#include "datadefinition.h"
#include "columndefinition.h"
#include "table.h"
#include "attributerecord.h"
#include "polygon.h"
#include "geometry.h"
#include "feature.h"
#include "symboltable.h"
#include "operationmetadata.h"
#include "operationExpression.h"
#include "operation.h"
#include "commandhandler.h"

Ilwis::Kernel *Ilwis::Kernel::_kernel = 0;

using namespace Ilwis;

Catalog *createCatalog()  {
    return new Catalog();
}

Ilwis::Kernel* kernel() {
    if (Kernel::_kernel == 0) {
        Kernel::_kernel = new Kernel();
        Kernel::_kernel->init();

    }
    return Kernel::_kernel;
}

Kernel::Kernel(QObject *parent) :
    QObject(parent), _version(0)
{
}

void Kernel::init() {

    if ( !_version.isNull())
        return;
     _issues.reset( new IssueLogger());

     issues()->log(QString("Ilwis started at %1").arg(Time::now().toString()),IssueObject::itMessage);

    _version.reset(new Version());
    _version->addBinaryVersion(Ilwis::Version::bvFORMAT30);
    _version->addBinaryVersion(Ilwis::Version::bvFORMATFOREIGN);
    _version->addBinaryVersion(Ilwis::Version::bvPOLYGONFORMAT37);
    _version->addODFVersion("3.1");

    _dbPublic = QSqlDatabase::addDatabase("QSQLITE");
    _dbPublic.setHostName("localhost");
    _dbPublic.setDatabaseName(":memory:");
    _dbPublic.open();

    _dbPublic.prepare();

    CatalogConnectorFactory *catfactory = new CatalogConnectorFactory();
    addFactory(catfactory);

    ConnectorFactory *confac = new ConnectorFactory();
    addFactory(confac);

    FeatureFactory *featureFac = new FeatureFactory();
    featureFac->addCreator("feature", createFeature);
    addFactory(featureFac);

    GeoRefImplementationFactory *georefFac = new GeoRefImplementationFactory();
    georefFac->prepare();
    addFactory(georefFac);

    _modules.addModules();

    mastercatalog()->addContainer(QUrl("ilwis://system"));

   // ItemRange::addCreateItem("ThematicItem", ThematicItem::createRange());

}

Kernel::~Kernel() {
    issues()->log(QString("Ilwis closed at %1").arg(Time::now().toString()),IssueObject::itMessage);
    _dbPublic.close();
    delete mastercatalog();
    delete context();

}

const QVariant *Kernel::getFromTLS(const QString& key) const{
    if (_caches.hasLocalData()) {
        return _caches.localData()->object(key);
    }
    return 0;
}

void Kernel::setTLS(const QString& key, QVariant* data){
    if (!_caches.hasLocalData())
        _caches.setLocalData(new QCache<QString, QVariant>);

    _caches.localData()->insert(key, data);
}

void Kernel::deleteTLS(const QString &key) {
    if (_caches.hasLocalData())
        _caches.localData()->remove(key);

}

QString Kernel::translate(const QString& s) const {
    //TODO implement translator class here and load in in the application object
    return s;
}

 const SPVersion& Kernel::version() const{
     return _version;
 }

PublicDatabase &Kernel::database()
{
    return _dbPublic;
}

QScopedPointer<IssueLogger>& Kernel::issues()
{
    return _issues;
}

void Kernel::addFactory(FactoryInterface *fac)
{
    QString key = fac->key().toLower();
    if (!_masterfactory.contains(key)) {
        _masterfactory[key]  = fac;
    }
}

QString Kernel::demangle(const char *mangled_name)
{
    int status;
    char *realname = abi::__cxa_demangle(mangled_name,0,0,&status);
    QString type(realname);
    free(realname);

    return type;
}

bool Kernel::error(const QString &message, const QString p1, const QString p2, const QString p3, const QString& file,  int line, const QString& func)
{
    QFileInfo inf(file);
    QString name = inf.fileName();
    quint64 issueid;
    if ( p1 == sUNDEF)
        issueid =issues()->log(TR(message));
    else if (p2 == sUNDEF)
        issueid =issues()->log(TR(message).arg(p1));
    else if ( p3 == sUNDEF)
        issueid =issues()->log(TR(message).arg(p1, p2));
    else
        issueid =issues()->log(TR(message).arg(p1).arg(p2).arg(p3));
    if ( issueid != i64UNDEF) {
        issues()->addCodeInfo(issueid, line, func, name);
    }
    return false;
}

void Kernel::startClock(){
    _start_clock = clock();
}

void Kernel::endClock(){
    clock_t end = clock();
    double total = (double)(end - _start_clock) / CLOCKS_PER_SEC;
    qDebug() << "calc old in " << total << " seconds";

}

<|endoftext|>


<commit_before>#ifndef __MEDIA_ELEMENT_IMPL_HPP__
#define __MEDIA_ELEMENT_IMPL_HPP__

#include "MediaObjectImpl.hpp"
#include "MediaElement.hpp"
#include "MediaType.hpp"
#include "MediaLatencyStat.hpp"
#include <EventHandler.hpp>
#include <gst/gst.h>
#include <mutex>
#include <set>
#include <random>
#include "MediaFlowOutStateChange.hpp"
#include "MediaFlowInStateChange.hpp"
#include "MediaFlowState.hpp"
#include "commons/kmselement.h"

namespace kurento
{

class MediaType;
class MediaElementImpl;
class AudioCodec;
class VideoCodec;
class MediaFlowData;

struct MediaTypeCmp {
  bool operator() (const std::shared_ptr<MediaType> &a,
                   const std::shared_ptr<MediaType> &b) const {
    return a->getValue () < b->getValue ();
  }
};

void Serialize (std::shared_ptr<MediaElementImpl> &object,
                JsonSerializer &serializer);

class ElementConnectionDataInternal;

class MediaElementImpl : public MediaObjectImpl, public virtual MediaElement
{

public:

  MediaElementImpl (const boost::property_tree::ptree &config,
                    std::shared_ptr<MediaObjectImpl> parent,
                    const std::string &factoryName);

  virtual ~MediaElementImpl ();

  GstElement *getGstreamerElement() {
    return element;
  };

  virtual std::map <std::string, std::shared_ptr<Stats>> getStats () override;
  virtual std::map <std::string, std::shared_ptr<Stats>> getStats (
        std::shared_ptr<MediaType> mediaType) override;

  virtual std::vector<std::shared_ptr<ElementConnectionData>>
      getSourceConnections () override;
  virtual std::vector<std::shared_ptr<ElementConnectionData>>
      getSourceConnections (
        std::shared_ptr<MediaType> mediaType) override;
  virtual std::vector<std::shared_ptr<ElementConnectionData>>
      getSourceConnections (
        std::shared_ptr<MediaType> mediaType, const std::string &description) override;
  virtual std::vector<std::shared_ptr<ElementConnectionData>>
      getSinkConnections () override;
  virtual std::vector<std::shared_ptr<ElementConnectionData>> getSinkConnections (
        std::shared_ptr<MediaType> mediaType) override;
  virtual std::vector<std::shared_ptr<ElementConnectionData>> getSinkConnections (
        std::shared_ptr<MediaType> mediaType, const std::string &description) override;
  virtual void connect (std::shared_ptr<MediaElement> sink) override;
  virtual void connect (std::shared_ptr<MediaElement> sink,
                        std::shared_ptr<MediaType> mediaType) override;
  virtual void connect (std::shared_ptr<MediaElement> sink,
                        std::shared_ptr<MediaType> mediaType,
                        const std::string &sourceMediaDescription) override;
  virtual void connect (std::shared_ptr<MediaElement> sink,
                        std::shared_ptr<MediaType> mediaType,
                        const std::string &sourceMediaDescription,
                        const std::string &sinkMediaDescription) override;
  virtual void disconnect (std::shared_ptr<MediaElement> sink) override;
  virtual void disconnect (std::shared_ptr<MediaElement> sink,
                           std::shared_ptr<MediaType> mediaType) override;
  virtual void disconnect (std::shared_ptr<MediaElement> sink,
                           std::shared_ptr<MediaType> mediaType,
                           const std::string &sourceMediaDescription) override;
  virtual void disconnect (std::shared_ptr<MediaElement> sink,
                           std::shared_ptr<MediaType> mediaType,
                           const std::string &sourceMediaDescription,
                           const std::string &sinkMediaDescription) override;
  void setAudioFormat (std::shared_ptr<AudioCaps> caps) override;
  void setVideoFormat (std::shared_ptr<VideoCaps> caps) override;

  virtual void release () override;

  virtual std::string getGstreamerDot () override;
  virtual std::string getGstreamerDot (std::shared_ptr<GstreamerDotDetails>
                                       details) override;

  virtual void setOutputBitrate (int bitrate) override;

  bool isMediaFlowingIn (std::shared_ptr<MediaType> mediaType) override;
  bool isMediaFlowingIn (std::shared_ptr<MediaType> mediaType,
                         const std::string &sinkMediaDescription) override;
  bool isMediaFlowingOut (std::shared_ptr<MediaType> mediaType) override;
  bool isMediaFlowingOut (std::shared_ptr<MediaType> mediaType,
                          const std::string &sourceMediaDescription) override;

  virtual int getMinOuputBitrate () override;
  virtual void setMinOuputBitrate (int minOuputBitrate) override;

  virtual int getMinOutputBitrate () override;
  virtual void setMinOutputBitrate (int minOutputBitrate) override;

  virtual int getMaxOuputBitrate () override;
  virtual void setMaxOuputBitrate (int maxOuputBitrate) override;

  virtual int getMaxOutputBitrate () override;
  virtual void setMaxOutputBitrate (int maxOutputBitrate) override;

  /* Next methods are automatically implemented by code generator */
  virtual bool connect (const std::string &eventType,
                        std::shared_ptr<EventHandler> handler) override;

  sigc::signal<void, ElementConnected> signalElementConnected;
  sigc::signal<void, ElementDisconnected> signalElementDisconnected;
  sigc::signal<void, MediaFlowOutStateChange> signalMediaFlowOutStateChange;
  sigc::signal<void, MediaFlowInStateChange> signalMediaFlowInStateChange;

  virtual void invoke (std::shared_ptr<MediaObjectImpl> obj,
                       const std::string &methodName, const Json::Value &params,
                       Json::Value &response) override;

  virtual void Serialize (JsonSerializer &serializer) override;

protected:
  GstElement *element;
  GstBus *bus;
  gulong handlerId;

  virtual void postConstructor () override;
  void collectLatencyStats (std::vector<std::shared_ptr<MediaLatencyStat>>
                            &latencyStats, const GstStructure *stats);
  virtual void fillStatsReport (std::map <std::string, std::shared_ptr<Stats>>
                                &report, const GstStructure *stats, double timestamp);

private:
  std::recursive_timed_mutex sourcesMutex;
  std::recursive_timed_mutex sinksMutex;

  std::map < std::shared_ptr <MediaType>, std::map < std::string,
      std::shared_ptr<ElementConnectionDataInternal >> , MediaTypeCmp > sources;
  std::map < std::shared_ptr <MediaType>, std::map < std::string,
      std::set<std::shared_ptr<ElementConnectionDataInternal> >> , MediaTypeCmp >
      sinks;

  std::mt19937_64 rnd {std::random_device{}() };
  std::uniform_int_distribution<> dist {1, 100};

  gulong padAddedHandlerId;
  gulong mediaFlowOutHandler;
  gulong mediaFlowInHandler;
  std::map <std::string, std::shared_ptr <MediaFlowData>> mediaFlowDataIn;
  std::map <std::string, std::shared_ptr <MediaFlowData>> mediaFlowDataOut;

  void disconnectAll();
  void performConnection (std::shared_ptr <ElementConnectionDataInternal> data);
  std::map <std::string, std::shared_ptr<Stats>> generateStats (
        const gchar *selector);
  void mediaFlowOutStateChange (gboolean isFlowing, gchar *padName,
                                KmsElementPadType type);
  void mediaFlowInStateChange (gboolean isFlowing, gchar *padName,
                               KmsElementPadType type);

  class StaticConstructor
  {
  public:
    StaticConstructor();
  };

  static StaticConstructor staticConstructor;

  friend void _media_element_impl_bus_message (GstBus *bus, GstMessage *message,
      gpointer data);
  friend void _media_element_pad_added (GstElement *elem, GstPad *pad,
                                        gpointer data);
};

} /* kurento */

#endif /*  __MEDIA_ELEMENT_IMPL_HPP__ */
<commit_msg>MediaElementImpl: Move mediaFlow structures from private to protected<commit_after>#ifndef __MEDIA_ELEMENT_IMPL_HPP__
#define __MEDIA_ELEMENT_IMPL_HPP__

#include "MediaObjectImpl.hpp"
#include "MediaElement.hpp"
#include "MediaType.hpp"
#include "MediaLatencyStat.hpp"
#include <EventHandler.hpp>
#include <gst/gst.h>
#include <mutex>
#include <set>
#include <random>
#include "MediaFlowOutStateChange.hpp"
#include "MediaFlowInStateChange.hpp"
#include "MediaFlowState.hpp"
#include "commons/kmselement.h"

namespace kurento
{

class MediaType;
class MediaElementImpl;
class AudioCodec;
class VideoCodec;
class MediaFlowData;

struct MediaTypeCmp {
  bool operator() (const std::shared_ptr<MediaType> &a,
                   const std::shared_ptr<MediaType> &b) const {
    return a->getValue () < b->getValue ();
  }
};

void Serialize (std::shared_ptr<MediaElementImpl> &object,
                JsonSerializer &serializer);

class ElementConnectionDataInternal;

class MediaElementImpl : public MediaObjectImpl, public virtual MediaElement
{

public:

  MediaElementImpl (const boost::property_tree::ptree &config,
                    std::shared_ptr<MediaObjectImpl> parent,
                    const std::string &factoryName);

  virtual ~MediaElementImpl ();

  GstElement *getGstreamerElement() {
    return element;
  };

  virtual std::map <std::string, std::shared_ptr<Stats>> getStats () override;
  virtual std::map <std::string, std::shared_ptr<Stats>> getStats (
        std::shared_ptr<MediaType> mediaType) override;

  virtual std::vector<std::shared_ptr<ElementConnectionData>>
      getSourceConnections () override;
  virtual std::vector<std::shared_ptr<ElementConnectionData>>
      getSourceConnections (
        std::shared_ptr<MediaType> mediaType) override;
  virtual std::vector<std::shared_ptr<ElementConnectionData>>
      getSourceConnections (
        std::shared_ptr<MediaType> mediaType, const std::string &description) override;
  virtual std::vector<std::shared_ptr<ElementConnectionData>>
      getSinkConnections () override;
  virtual std::vector<std::shared_ptr<ElementConnectionData>> getSinkConnections (
        std::shared_ptr<MediaType> mediaType) override;
  virtual std::vector<std::shared_ptr<ElementConnectionData>> getSinkConnections (
        std::shared_ptr<MediaType> mediaType, const std::string &description) override;
  virtual void connect (std::shared_ptr<MediaElement> sink) override;
  virtual void connect (std::shared_ptr<MediaElement> sink,
                        std::shared_ptr<MediaType> mediaType) override;
  virtual void connect (std::shared_ptr<MediaElement> sink,
                        std::shared_ptr<MediaType> mediaType,
                        const std::string &sourceMediaDescription) override;
  virtual void connect (std::shared_ptr<MediaElement> sink,
                        std::shared_ptr<MediaType> mediaType,
                        const std::string &sourceMediaDescription,
                        const std::string &sinkMediaDescription) override;
  virtual void disconnect (std::shared_ptr<MediaElement> sink) override;
  virtual void disconnect (std::shared_ptr<MediaElement> sink,
                           std::shared_ptr<MediaType> mediaType) override;
  virtual void disconnect (std::shared_ptr<MediaElement> sink,
                           std::shared_ptr<MediaType> mediaType,
                           const std::string &sourceMediaDescription) override;
  virtual void disconnect (std::shared_ptr<MediaElement> sink,
                           std::shared_ptr<MediaType> mediaType,
                           const std::string &sourceMediaDescription,
                           const std::string &sinkMediaDescription) override;
  void setAudioFormat (std::shared_ptr<AudioCaps> caps) override;
  void setVideoFormat (std::shared_ptr<VideoCaps> caps) override;

  virtual void release () override;

  virtual std::string getGstreamerDot () override;
  virtual std::string getGstreamerDot (std::shared_ptr<GstreamerDotDetails>
                                       details) override;

  virtual void setOutputBitrate (int bitrate) override;

  bool isMediaFlowingIn (std::shared_ptr<MediaType> mediaType) override;
  bool isMediaFlowingIn (std::shared_ptr<MediaType> mediaType,
                         const std::string &sinkMediaDescription) override;
  bool isMediaFlowingOut (std::shared_ptr<MediaType> mediaType) override;
  bool isMediaFlowingOut (std::shared_ptr<MediaType> mediaType,
                          const std::string &sourceMediaDescription) override;

  virtual int getMinOuputBitrate () override;
  virtual void setMinOuputBitrate (int minOuputBitrate) override;

  virtual int getMinOutputBitrate () override;
  virtual void setMinOutputBitrate (int minOutputBitrate) override;

  virtual int getMaxOuputBitrate () override;
  virtual void setMaxOuputBitrate (int maxOuputBitrate) override;

  virtual int getMaxOutputBitrate () override;
  virtual void setMaxOutputBitrate (int maxOutputBitrate) override;

  /* Next methods are automatically implemented by code generator */
  virtual bool connect (const std::string &eventType,
                        std::shared_ptr<EventHandler> handler) override;

  sigc::signal<void, ElementConnected> signalElementConnected;
  sigc::signal<void, ElementDisconnected> signalElementDisconnected;
  sigc::signal<void, MediaFlowOutStateChange> signalMediaFlowOutStateChange;
  sigc::signal<void, MediaFlowInStateChange> signalMediaFlowInStateChange;

  virtual void invoke (std::shared_ptr<MediaObjectImpl> obj,
                       const std::string &methodName, const Json::Value &params,
                       Json::Value &response) override;

  virtual void Serialize (JsonSerializer &serializer) override;

protected:
  GstElement *element;
  GstBus *bus;
  gulong handlerId;
  std::map <std::string, std::shared_ptr <MediaFlowData>> mediaFlowDataIn;
  std::map <std::string, std::shared_ptr <MediaFlowData>> mediaFlowDataOut;

  virtual void postConstructor () override;
  void collectLatencyStats (std::vector<std::shared_ptr<MediaLatencyStat>>
                            &latencyStats, const GstStructure *stats);
  virtual void fillStatsReport (std::map <std::string, std::shared_ptr<Stats>>
                                &report, const GstStructure *stats, double timestamp);

private:
  std::recursive_timed_mutex sourcesMutex;
  std::recursive_timed_mutex sinksMutex;

  std::map < std::shared_ptr <MediaType>, std::map < std::string,
      std::shared_ptr<ElementConnectionDataInternal >> , MediaTypeCmp > sources;
  std::map < std::shared_ptr <MediaType>, std::map < std::string,
      std::set<std::shared_ptr<ElementConnectionDataInternal> >> , MediaTypeCmp >
      sinks;

  std::mt19937_64 rnd {std::random_device{}() };
  std::uniform_int_distribution<> dist {1, 100};

  gulong padAddedHandlerId;
  gulong mediaFlowOutHandler;
  gulong mediaFlowInHandler;

  void disconnectAll();
  void performConnection (std::shared_ptr <ElementConnectionDataInternal> data);
  std::map <std::string, std::shared_ptr<Stats>> generateStats (
        const gchar *selector);
  void mediaFlowOutStateChange (gboolean isFlowing, gchar *padName,
                                KmsElementPadType type);
  void mediaFlowInStateChange (gboolean isFlowing, gchar *padName,
                               KmsElementPadType type);

  class StaticConstructor
  {
  public:
    StaticConstructor();
  };

  static StaticConstructor staticConstructor;

  friend void _media_element_impl_bus_message (GstBus *bus, GstMessage *message,
      gpointer data);
  friend void _media_element_pad_added (GstElement *elem, GstPad *pad,
                                        gpointer data);
};

} /* kurento */

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


<commit_before>#include "Decoder_LDPC_BP_peeling.hpp"

#include "Tools/Perf/common/hard_decide.h"
#include "Tools/Noise/Erased_value.hpp"
#include "Tools/Math/utils.h"

using namespace aff3ct;
using namespace aff3ct::module;

template<typename B, typename R>
Decoder_LDPC_BP_peeling<B, R>::Decoder_LDPC_BP_peeling(const int K, const int N, const int n_ite,
                                                       const tools::Sparse_matrix &H,
                                                       const std::vector<unsigned> &info_bits_pos,
                                                       const bool enable_syndrome, const int syndrome_depth,
                                                       const int n_frames)
: Decoder                (K, N,                                            n_frames, 1),
  Decoder_LDPC_BP<B,R>   (K, N, n_ite, H, enable_syndrome, syndrome_depth, n_frames, 1),
  info_bits_pos          (info_bits_pos                                               ),
  var_nodes              (n_frames, std::vector<B>(N             )                    ),
  check_nodes            (n_frames, std::vector<B>(H.get_n_cols())                    )
{
	const std::string name = "Decoder_LDPC_BP_peeling";
	this->set_name(name);
}

template <typename B, typename R>
void Decoder_LDPC_BP_peeling<B,R>
::_load(const R *Y_N, const int frame_id)
{
	tools::hard_decide(Y_N, var_nodes[frame_id].data(), this->N);
	for (auto i = 0; i < this->N; i++)
		if (Y_N[i] <= tools::Erased_value<R>::llr && Y_N[i] >= -tools::Erased_value<R>::llr)
			var_nodes[frame_id][i] = tools::Erased_value<B>::symbol;
}

template <typename B, typename R>
void Decoder_LDPC_BP_peeling<B,R>
::_decode(const int frame_id)
{
	auto links = this->H;

	std::fill(this->check_nodes[frame_id].begin(), this->check_nodes[frame_id].end(), (B)0);

	// std::cout << "(L) var_nodes : " << std::endl;
	// for (unsigned i = 0; i < this->var_nodes[frame_id].size(); i++)
	// 	std::cout << this->var_nodes[frame_id][i] << " ";
	// std::cout << std::endl;
	// std::cout << "(L) check_nodes : " << std::endl;
	// for (unsigned i = 0; i < this->check_nodes[frame_id].size(); i++)
	// 	std::cout << this->check_nodes[frame_id][i] << " ";
	// std::cout << std::endl;

	// std::cout << "(L) links : " << std::endl;
	// links.print(true);

	// first propagate known values
	for (unsigned i = 0; i < links.get_n_rows(); i++)
	{
		auto cur_state = this->var_nodes[frame_id][i];
		if (cur_state != tools::Erased_value<B>::symbol)
		{
			auto& cn_list = links.get_row_to_cols()[i];
			while (cn_list.size())
			{
				auto& cn_pos = cn_list.front();

				this->check_nodes[frame_id][cn_pos] ^= cur_state;
				links.rm_connection(i, cn_pos);
			}
		}
	}

	// std::cout << "(I) var_nodes : " << std::endl;
	// for (unsigned i = 0; i < this->var_nodes[frame_id].size(); i++)
	// 	std::cout << this->var_nodes[frame_id][i] << " ";
	// std::cout << std::endl;
	// std::cout << "(I) check_nodes : " << std::endl;
	// for (unsigned i = 0; i < this->check_nodes[frame_id].size(); i++)
	// 	std::cout << this->check_nodes[frame_id][i] << " ";
	// std::cout << std::endl;

	// std::cout << "(I) links : " << std::endl;
	// links.print(true);

	for (auto ite = 0; ite < this->n_ite; ite++)
	{
		bool all_check_nodes_done = true;

		// find degree-1 check nodes
		for (unsigned i = 0; i < links.get_n_cols(); i++)
		{
			if (links.get_col_to_rows()[i].size() == 1)
			{ // then propagate the belief
				auto& vn_pos = links.get_col_to_rows()[i].front();
				this->var_nodes  [frame_id][vn_pos] = this->check_nodes[frame_id][i];
				this->check_nodes[frame_id][     i] = 0;
				links.rm_connection(vn_pos, i);
			}
			else
				all_check_nodes_done &= links.get_col_to_rows()[i].size() == 0;
		}

		// std::cout << "(" << ite << ") var_nodes : " << std::endl;
		// for (unsigned i = 0; i < this->var_nodes[frame_id].size(); i++)
		// 	std::cout << this->var_nodes[frame_id][i] << " ";
		// std::cout << std::endl;
		// std::cout << "(" << ite << ") check_nodes : " << std::endl;
		// for (unsigned i = 0; i < this->check_nodes[frame_id].size(); i++)
		// 	std::cout << this->check_nodes[frame_id][i] << " ";
		// std::cout << std::endl;

		if (all_check_nodes_done)
			break;
	}
};

template <typename B, typename R>
void Decoder_LDPC_BP_peeling<B,R>
::_decode_hiho(const B *Y_N, B *V_K, const int frame_id)
{
//	auto t_load = std::chrono::steady_clock::now();  // ---------------------------------------------------------- LOAD
	std::copy(Y_N, Y_N + this->N, var_nodes[frame_id].data());
//	auto d_load = std::chrono::steady_clock::now() - t_load;

//	auto t_decod = std::chrono::steady_clock::now(); // -------------------------------------------------------- DECODE
	this->_decode(frame_id);
//	auto d_decod = std::chrono::steady_clock::now() - t_decod;

//	auto t_store = std::chrono::steady_clock::now(); // --------------------------------------------------------- STORE
	_store(V_K, frame_id);
//	auto d_store = std::chrono::steady_clock::now() - t_store;

//	(*this)[dec::tsk::decode_hiho].update_timer(dec::tm::decode_hiho::decode, d_decod);
//	(*this)[dec::tsk::decode_hiho].update_timer(dec::tm::decode_hiho::store,  d_store);
}

template <typename B, typename R>
void Decoder_LDPC_BP_peeling<B,R>
::_decode_hiho_cw(const B *Y_N, B *V_N, const int frame_id)
{
//	auto t_load = std::chrono::steady_clock::now();  // ---------------------------------------------------------- LOAD
	std::copy(Y_N, Y_N + this->N, var_nodes[frame_id].data());
//	auto d_load = std::chrono::steady_clock::now() - t_load;

//	auto t_decod = std::chrono::steady_clock::now(); // -------------------------------------------------------- DECODE
	this->_decode(frame_id);
//	auto d_decod = std::chrono::steady_clock::now() - t_decod;

//	auto t_store = std::chrono::steady_clock::now(); // --------------------------------------------------------- STORE
	_store_cw(V_N, frame_id);
//	auto d_store = std::chrono::steady_clock::now() - t_store;

//	(*this)[dec::tsk::decode_hiho_cw].update_timer(dec::tm::decode_hiho_cw::decode, d_decod);
//	(*this)[dec::tsk::decode_hiho_cw].update_timer(dec::tm::decode_hiho_cw::store,  d_store);
}

template <typename B, typename R>
void Decoder_LDPC_BP_peeling<B,R>
::_decode_siho(const R *Y_N, B *V_K, const int frame_id)
{
//	auto t_load = std::chrono::steady_clock::now();  // ---------------------------------------------------------- LOAD
	this->_load(Y_N, frame_id);
//	auto d_load = std::chrono::steady_clock::now() - t_load;

//	auto t_decod = std::chrono::steady_clock::now(); // -------------------------------------------------------- DECODE
	this->_decode(frame_id);
//	auto d_decod = std::chrono::steady_clock::now() - t_decod;

//	auto t_store = std::chrono::steady_clock::now(); // --------------------------------------------------------- STORE
	_store(V_K, frame_id);
//	auto d_store = std::chrono::steady_clock::now() - t_store;

//	(*this)[dec::tsk::decode_siho].update_timer(dec::tm::decode_siho::load,   d_load);
//	(*this)[dec::tsk::decode_siho].update_timer(dec::tm::decode_siho::decode, d_decod);
//	(*this)[dec::tsk::decode_siho].update_timer(dec::tm::decode_siho::store,  d_store);
}

template <typename B, typename R>
void Decoder_LDPC_BP_peeling<B,R>
::_decode_siho_cw(const R *Y_N, B *V_N, const int frame_id)
{
//	auto t_load = std::chrono::steady_clock::now();  // ---------------------------------------------------------- LOAD
	this->_load(Y_N, frame_id);
//	auto d_load = std::chrono::steady_clock::now() - t_load;

//	auto t_decod = std::chrono::steady_clock::now(); // -------------------------------------------------------- DECODE
	this->_decode(frame_id);
//	auto d_decod = std::chrono::steady_clock::now() - t_decod;

//	auto t_store = std::chrono::steady_clock::now(); // --------------------------------------------------------- STORE
	_store_cw(V_N, frame_id);
//	auto d_store = std::chrono::steady_clock::now() - t_store;

//	(*this)[dec::tsk::decode_siho_cw].update_timer(dec::tm::decode_siho_cw::load,   d_load);
//	(*this)[dec::tsk::decode_siho_cw].update_timer(dec::tm::decode_siho_cw::decode, d_decod);
//	(*this)[dec::tsk::decode_siho_cw].update_timer(dec::tm::decode_siho_cw::store,  d_store);
}

template<typename B, typename R>
void Decoder_LDPC_BP_peeling<B, R>::_store(B *V_K, const int frame_id)
{
	for (auto i = 0; i < this->K; i++)
		V_K[i] = this->var_nodes[frame_id][this->info_bits_pos[i]];
}

template<typename B, typename R>
void Decoder_LDPC_BP_peeling<B, R>::_store_cw(B *V_N, const int frame_id)
{
	std::copy(this->var_nodes[frame_id].begin(), this->var_nodes[frame_id].end(), V_N);
}

// ==================================================================================== explicit template instantiation
#include "Tools/types.h"
#ifdef MULTI_PREC
template class aff3ct::module::Decoder_LDPC_BP_peeling<B_8,Q_8>;
template class aff3ct::module::Decoder_LDPC_BP_peeling<B_16,Q_16>;
template class aff3ct::module::Decoder_LDPC_BP_peeling<B_32,Q_32>;
template class aff3ct::module::Decoder_LDPC_BP_peeling<B_64,Q_64>;
#else
template class aff3ct::module::Decoder_LDPC_BP_peeling<B,Q>;
#endif
// ==================================================================================== explicit template instantiation
<commit_msg>Add a no modification syndrome and handle the syndrome depth<commit_after>#include "Decoder_LDPC_BP_peeling.hpp"

#include "Tools/Perf/common/hard_decide.h"
#include "Tools/Noise/Erased_value.hpp"
#include "Tools/Math/utils.h"

using namespace aff3ct;
using namespace aff3ct::module;

template<typename B, typename R>
Decoder_LDPC_BP_peeling<B, R>::Decoder_LDPC_BP_peeling(const int K, const int N, const int n_ite,
                                                       const tools::Sparse_matrix &H,
                                                       const std::vector<unsigned> &info_bits_pos,
                                                       const bool enable_syndrome, const int syndrome_depth,
                                                       const int n_frames)
: Decoder                (K, N,                                            n_frames, 1),
  Decoder_LDPC_BP<B,R>   (K, N, n_ite, H, enable_syndrome, syndrome_depth, n_frames, 1),
  info_bits_pos          (info_bits_pos                                               ),
  var_nodes              (n_frames, std::vector<B>(N             )                    ),
  check_nodes            (n_frames, std::vector<B>(H.get_n_cols())                    )
{
	const std::string name = "Decoder_LDPC_BP_peeling";
	this->set_name(name);
}

template <typename B, typename R>
void Decoder_LDPC_BP_peeling<B,R>
::_load(const R *Y_N, const int frame_id)
{
	tools::hard_decide(Y_N, var_nodes[frame_id].data(), this->N);
	for (auto i = 0; i < this->N; i++)
		if (Y_N[i] <= tools::Erased_value<R>::llr && Y_N[i] >= -tools::Erased_value<R>::llr)
			var_nodes[frame_id][i] = tools::Erased_value<B>::symbol;
}

template <typename B, typename R>
void Decoder_LDPC_BP_peeling<B,R>
::_decode(const int frame_id)
{
	auto links = this->H;

	std::fill(this->check_nodes[frame_id].begin(), this->check_nodes[frame_id].end(), (B)0);

	// std::cout << "(L) var_nodes : " << std::endl;
	// for (unsigned i = 0; i < this->var_nodes[frame_id].size(); i++)
	// 	std::cout << this->var_nodes[frame_id][i] << " ";
	// std::cout << std::endl;
	// std::cout << "(L) check_nodes : " << std::endl;
	// for (unsigned i = 0; i < this->check_nodes[frame_id].size(); i++)
	// 	std::cout << this->check_nodes[frame_id][i] << " ";
	// std::cout << std::endl;

	// std::cout << "(L) links : " << std::endl;
	// links.print(true);

	// first propagate known values
	for (unsigned i = 0; i < links.get_n_rows(); i++)
	{
		auto cur_state = this->var_nodes[frame_id][i];
		if (cur_state != tools::Erased_value<B>::symbol)
		{
			auto& cn_list = links.get_row_to_cols()[i];
			while (cn_list.size())
			{
				auto& cn_pos = cn_list.front();

				this->check_nodes[frame_id][cn_pos] ^= cur_state;
				links.rm_connection(i, cn_pos);
			}
		}
	}

	// std::cout << "(I) var_nodes : " << std::endl;
	// for (unsigned i = 0; i < this->var_nodes[frame_id].size(); i++)
	// 	std::cout << this->var_nodes[frame_id][i] << " ";
	// std::cout << std::endl;
	// std::cout << "(I) check_nodes : " << std::endl;
	// for (unsigned i = 0; i < this->check_nodes[frame_id].size(); i++)
	// 	std::cout << this->check_nodes[frame_id][i] << " ";
	// std::cout << std::endl;

	// std::cout << "(I) links : " << std::endl;
	// links.print(true);

	for (auto ite = 0; ite < this->n_ite; ite++)
	{
		bool all_check_nodes_done = true, no_modification = true;

		// find degree-1 check nodes
		for (unsigned i = 0; i < links.get_n_cols(); i++)
		{
			if (links.get_col_to_rows()[i].size() == 1)
			{ // then propagate the belief
				auto& vn_pos = links.get_col_to_rows()[i].front();
				this->var_nodes  [frame_id][vn_pos] = this->check_nodes[frame_id][i];
				this->check_nodes[frame_id][     i] = 0;
				links.rm_connection(vn_pos, i);
				no_modification = false;
			}
			else
				all_check_nodes_done &= links.get_col_to_rows()[i].size() == 0;
		}

		// std::cout << "(" << ite << ") var_nodes : " << std::endl;
		// for (unsigned i = 0; i < this->var_nodes[frame_id].size(); i++)
		// 	std::cout << this->var_nodes[frame_id][i] << " ";
		// std::cout << std::endl;
		// std::cout << "(" << ite << ") check_nodes : " << std::endl;
		// for (unsigned i = 0; i < this->check_nodes[frame_id].size(); i++)
		// 	std::cout << this->check_nodes[frame_id][i] << " ";
		// std::cout << std::endl;

		if (this->enable_syndrome && (all_check_nodes_done || no_modification))
		{
			this->cur_syndrome_depth++;
			if (this->cur_syndrome_depth == this->syndrome_depth)
				break;
		}
		else
			this->cur_syndrome_depth = 0;
	}
};

template <typename B, typename R>
void Decoder_LDPC_BP_peeling<B,R>
::_decode_hiho(const B *Y_N, B *V_K, const int frame_id)
{
//	auto t_load = std::chrono::steady_clock::now();  // ---------------------------------------------------------- LOAD
	std::copy(Y_N, Y_N + this->N, var_nodes[frame_id].data());
//	auto d_load = std::chrono::steady_clock::now() - t_load;

//	auto t_decod = std::chrono::steady_clock::now(); // -------------------------------------------------------- DECODE
	this->_decode(frame_id);
//	auto d_decod = std::chrono::steady_clock::now() - t_decod;

//	auto t_store = std::chrono::steady_clock::now(); // --------------------------------------------------------- STORE
	_store(V_K, frame_id);
//	auto d_store = std::chrono::steady_clock::now() - t_store;

//	(*this)[dec::tsk::decode_hiho].update_timer(dec::tm::decode_hiho::decode, d_decod);
//	(*this)[dec::tsk::decode_hiho].update_timer(dec::tm::decode_hiho::store,  d_store);
}

template <typename B, typename R>
void Decoder_LDPC_BP_peeling<B,R>
::_decode_hiho_cw(const B *Y_N, B *V_N, const int frame_id)
{
//	auto t_load = std::chrono::steady_clock::now();  // ---------------------------------------------------------- LOAD
	std::copy(Y_N, Y_N + this->N, var_nodes[frame_id].data());
//	auto d_load = std::chrono::steady_clock::now() - t_load;

//	auto t_decod = std::chrono::steady_clock::now(); // -------------------------------------------------------- DECODE
	this->_decode(frame_id);
//	auto d_decod = std::chrono::steady_clock::now() - t_decod;

//	auto t_store = std::chrono::steady_clock::now(); // --------------------------------------------------------- STORE
	_store_cw(V_N, frame_id);
//	auto d_store = std::chrono::steady_clock::now() - t_store;

//	(*this)[dec::tsk::decode_hiho_cw].update_timer(dec::tm::decode_hiho_cw::decode, d_decod);
//	(*this)[dec::tsk::decode_hiho_cw].update_timer(dec::tm::decode_hiho_cw::store,  d_store);
}

template <typename B, typename R>
void Decoder_LDPC_BP_peeling<B,R>
::_decode_siho(const R *Y_N, B *V_K, const int frame_id)
{
//	auto t_load = std::chrono::steady_clock::now();  // ---------------------------------------------------------- LOAD
	this->_load(Y_N, frame_id);
//	auto d_load = std::chrono::steady_clock::now() - t_load;

//	auto t_decod = std::chrono::steady_clock::now(); // -------------------------------------------------------- DECODE
	this->_decode(frame_id);
//	auto d_decod = std::chrono::steady_clock::now() - t_decod;

//	auto t_store = std::chrono::steady_clock::now(); // --------------------------------------------------------- STORE
	_store(V_K, frame_id);
//	auto d_store = std::chrono::steady_clock::now() - t_store;

//	(*this)[dec::tsk::decode_siho].update_timer(dec::tm::decode_siho::load,   d_load);
//	(*this)[dec::tsk::decode_siho].update_timer(dec::tm::decode_siho::decode, d_decod);
//	(*this)[dec::tsk::decode_siho].update_timer(dec::tm::decode_siho::store,  d_store);
}

template <typename B, typename R>
void Decoder_LDPC_BP_peeling<B,R>
::_decode_siho_cw(const R *Y_N, B *V_N, const int frame_id)
{
//	auto t_load = std::chrono::steady_clock::now();  // ---------------------------------------------------------- LOAD
	this->_load(Y_N, frame_id);
//	auto d_load = std::chrono::steady_clock::now() - t_load;

//	auto t_decod = std::chrono::steady_clock::now(); // -------------------------------------------------------- DECODE
	this->_decode(frame_id);
//	auto d_decod = std::chrono::steady_clock::now() - t_decod;

//	auto t_store = std::chrono::steady_clock::now(); // --------------------------------------------------------- STORE
	_store_cw(V_N, frame_id);
//	auto d_store = std::chrono::steady_clock::now() - t_store;

//	(*this)[dec::tsk::decode_siho_cw].update_timer(dec::tm::decode_siho_cw::load,   d_load);
//	(*this)[dec::tsk::decode_siho_cw].update_timer(dec::tm::decode_siho_cw::decode, d_decod);
//	(*this)[dec::tsk::decode_siho_cw].update_timer(dec::tm::decode_siho_cw::store,  d_store);
}

template<typename B, typename R>
void Decoder_LDPC_BP_peeling<B, R>::_store(B *V_K, const int frame_id)
{
	for (auto i = 0; i < this->K; i++)
		V_K[i] = this->var_nodes[frame_id][this->info_bits_pos[i]];
}

template<typename B, typename R>
void Decoder_LDPC_BP_peeling<B, R>::_store_cw(B *V_N, const int frame_id)
{
	std::copy(this->var_nodes[frame_id].begin(), this->var_nodes[frame_id].end(), V_N);
}

// ==================================================================================== explicit template instantiation
#include "Tools/types.h"
#ifdef MULTI_PREC
template class aff3ct::module::Decoder_LDPC_BP_peeling<B_8,Q_8>;
template class aff3ct::module::Decoder_LDPC_BP_peeling<B_16,Q_16>;
template class aff3ct::module::Decoder_LDPC_BP_peeling<B_32,Q_32>;
template class aff3ct::module::Decoder_LDPC_BP_peeling<B_64,Q_64>;
#else
template class aff3ct::module::Decoder_LDPC_BP_peeling<B,Q>;
#endif
// ==================================================================================== explicit template instantiation
<|endoftext|>


<commit_before>/** @file

  @section license License

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
 */

#include "ts/RbTree.h"

namespace ts
{
namespace detail
{
  /// Equality.
  /// @note If @a n is @c NULL it is treated as having the color @c BLACK.
  /// @return @c true if @a c and the color of @a n are the same.
  inline bool
  operator==(RBNode *n, RBNode::Color c)
  {
    return c == (n ? n->getColor() : RBNode::BLACK);
  }
  /// Equality.
  /// @note If @a n is @c NULL it is treated as having the color @c BLACK.
  /// @return @c true if @a c and the color of @a n are the same.
  inline bool
  operator==(RBNode::Color c, RBNode *n)
  {
    return n == c;
  }

  RBNode *
  RBNode::getChild(Direction d) const
  {
    return d == RIGHT ? _right : d == LEFT ? _left : nullptr;
  }

  RBNode *
  RBNode::rotate(Direction d)
  {
    self *parent        = _parent; // Cache because it can change before we use it.
    Direction child_dir = _parent ? _parent->getChildDirection(this) : NONE;
    Direction other_dir = this->flip(d);
    self *child         = this;

    if (d != NONE && this->getChild(other_dir)) {
      child = this->getChild(other_dir);
      this->clearChild(other_dir);
      this->setChild(child->getChild(d), other_dir);
      child->clearChild(d);
      child->setChild(this, d);
      child->structureFixup();
      this->structureFixup();
      if (parent) {
        parent->clearChild(child_dir);
        parent->setChild(child, child_dir);
      } else {
        child->_parent = nullptr;
      }
    }
    return child;
  }

  RBNode *
  RBNode::setChild(self *n, Direction d)
  {
    if (n) {
      n->_parent = this;
    }
    if (d == RIGHT) {
      _right = n;
    } else if (d == LEFT) {
      _left = n;
    }
    return n;
  }

  // Returns the root node
  RBNode *
  RBNode::rippleStructureFixup()
  {
    self *root = this; // last node seen, root node at the end
    self *p    = this;
    while (p) {
      p->structureFixup();
      root = p;
      p    = root->_parent;
    }
    return root;
  }

  void
  RBNode::replaceWith(self *n)
  {
    n->_color = _color;
    if (_parent) {
      Direction d = _parent->getChildDirection(this);
      _parent->setChild(nullptr, d);
      if (_parent != n) {
        _parent->setChild(n, d);
      }
    } else {
      n->_parent = nullptr;
    }
    n->_left = n->_right = nullptr;
    if (_left && _left != n) {
      n->setChild(_left, LEFT);
    }
    if (_right && _right != n) {
      n->setChild(_right, RIGHT);
    }
    _left = _right = nullptr;
  }

  /* Rebalance the tree. This node is the unbalanced node. */
  RBNode *
  RBNode::rebalanceAfterInsert()
  {
    self *x(this); // the node with the imbalance

    while (x && x->_parent == RED) {
      Direction child_dir = NONE;

      if (x->_parent->_parent) {
        child_dir = x->_parent->_parent->getChildDirection(x->_parent);
      } else {
        break;
      }
      Direction other_dir(flip(child_dir));

      self *y = x->_parent->_parent->getChild(other_dir);
      if (y == RED) {
        x->_parent->_color = BLACK;
        y->_color          = BLACK;
        x                  = x->_parent->_parent;
        x->_color          = RED;
      } else {
        if (x->_parent->getChild(other_dir) == x) {
          x = x->_parent;
          x->rotate(child_dir);
        }
        // Note setting the parent color to BLACK causes the loop to exit.
        x->_parent->_color          = BLACK;
        x->_parent->_parent->_color = RED;
        x->_parent->_parent->rotate(other_dir);
      }
    }

    // every node above this one has a subtree structure change,
    // so notify it. serendipitously, this makes it easy to return
    // the new root node.
    self *root   = this->rippleStructureFixup();
    root->_color = BLACK;

    return root;
  }

  // Returns new root node
  RBNode *
  RBNode::remove()
  {
    self *root = nullptr; // new root node, returned to caller

    /*  Handle two special cases first.
        - This is the only node in the tree, return a new root of NIL
        - This is the root node with only one child, return that child as new root
    */
    if (!_parent && !(_left && _right)) {
      if (_left) {
        _left->_parent = nullptr;
        root           = _left;
        root->_color   = BLACK;
      } else if (_right) {
        _right->_parent = nullptr;
        root            = _right;
        root->_color    = BLACK;
      } // else that was the only node, so leave @a root @c NULL.
      return root;
    }

    /*  The node to be removed from the tree.
        If @c this (the target node) has both children, we remove
        its successor, which cannot have a left child and
        put that node in place of the target node. Otherwise this
        node has at most one child, so we can remove it.
        Note that the successor of a node with a right child is always
        a right descendant of the node. Therefore, remove_node
        is an element of the tree rooted at this node.
        Because of the initial special case checks, we know
        that remove_node is @b not the root node.
    */
    self *remove_node(_left && _right ? _right->leftmostDescendant() : this);

    // This is the color of the node physically removed from the tree.
    // Normally this is the color of @a remove_node
    Color remove_color = remove_node->_color;
    // Need to remember the direction from @a remove_node to @a splice_node
    Direction d(NONE);

    // The child node that will be promoted to replace the removed node.
    // The choice of left or right is irrelevant, as remove_node has at
    // most one child (and splice_node may be NIL if remove_node has no
    // children).
    self *splice_node(remove_node->_left ? remove_node->_left : remove_node->_right);

    if (splice_node) {
      // @c replace_with copies color so in this case the actual color
      // lost is that of the splice_node.
      remove_color = splice_node->_color;
      remove_node->replaceWith(splice_node);
    } else {
      // No children on remove node so we can just clip it off the tree
      // We update splice_node to maintain the invariant that it is
      // the node where the physical removal occurred.
      splice_node = remove_node->_parent;
      // Keep @a d up to date.
      d = splice_node->getChildDirection(remove_node);
      splice_node->setChild(nullptr, d);
    }

    // If the node to pull out of the tree isn't this one,
    // then replace this node in the tree with that removed
    // node in liu of copying the data over.
    if (remove_node != this) {
      // Don't leave @a splice_node referring to a removed node
      if (splice_node == this) {
        splice_node = remove_node;
      }
      this->replaceWith(remove_node);
    }

    root         = splice_node->rebalanceAfterRemove(remove_color, d);
    root->_color = BLACK;
    return root;
  }

  /**
   * Rebalance tree after a deletion
   * Called on the spliced in node or its parent, whichever is not NIL.
   * This modifies the tree structure only if @a c is @c BLACK.
   */
  RBNode *
  RBNode::rebalanceAfterRemove(Color c,    //!< The color of the removed node
                               Direction d //!< Direction of removed node from its parent
  )
  {
    self *root;

    if (BLACK == c) { // only rebalance if too much black
      self *n      = this;
      self *parent = n->_parent;

      // If @a direction is set, then we need to start at a leaf pseudo-node.
      // This is why we need @a parent, otherwise we could just use @a n.
      if (NONE != d) {
        parent = n;
        n      = nullptr;
      }

      while (parent) { // @a n is not the root
        // If the current node is RED, we can just recolor and be done
        if (n == RED) {
          n->_color = BLACK;
          break;
        } else {
          // Parameterizing the rebalance logic on the directions. We
          // write for the left child case and flip directions for the
          // right child case
          Direction near(LEFT), far(RIGHT);
          if ((NONE == d && parent->getChildDirection(n) == RIGHT) || RIGHT == d) {
            near = RIGHT;
            far  = LEFT;
          }

          self *w = parent->getChild(far); // sibling(n)

          if (w->_color == RED) {
            w->_color      = BLACK;
            parent->_color = RED;
            parent->rotate(near);
            w = parent->getChild(far);
          }

          self *wfc = w->getChild(far);
          if (w->getChild(near) == BLACK && wfc == BLACK) {
            w->_color = RED;
            n         = parent;
            parent    = n->_parent;
            d         = NONE; // Cancel any leaf node logic
          } else {
            if (wfc->_color == BLACK) {
              w->getChild(near)->_color = BLACK;
              w->_color                 = RED;
              w->rotate(far);
              w   = parent->getChild(far);
              wfc = w->getChild(far); // w changed, update far child cache.
            }
            w->_color      = parent->_color;
            parent->_color = BLACK;
            wfc->_color    = BLACK;
            parent->rotate(near);
            break;
          }
        }
      }
    }
    root = this->rippleStructureFixup();
    return root;
  }

  /** Ensure that the local information associated with each node is
      correct globally This should only be called on debug builds as it
      breaks any efficiencies we have gained from our tree structure.
      */
  int
  RBNode::validate()
  {
#if 0
  int black_ht = 0;
  int black_ht1, black_ht2;

  if (_left) {
    black_ht1 = _left->validate();
  }
  else
    black_ht1 = 1;

  if (black_ht1 > 0 && _right)
    black_ht2 = _right->validate();
  else
    black_ht2 = 1;

  if (black_ht1 == black_ht2) {
    black_ht = black_ht1;
    if (this->_color == BLACK)
      ++black_ht;
    else {  // No red-red
      if (_left == RED)
        black_ht = 0;
      else if (_right == RED)
        black_ht = 0;
      if (black_ht == 0)
        std::cout << "Red-red child\n";
    }
  } else {
    std::cout << "Height mismatch " << black_ht1 << " " << black_ht2 << "\n";
  }
  if (black_ht > 0 && !this->structureValidate())
    black_ht = 0;

  return black_ht;
#else
    return 0;
#endif
  }
} // namespace detail
} // namespace ts
<commit_msg>Coverity 1021989<commit_after>/** @file

  @section license License

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
 */

#include "ts/RbTree.h"

namespace ts
{
namespace detail
{
  /// Equality.
  /// @note If @a n is @c NULL it is treated as having the color @c BLACK.
  /// @return @c true if @a c and the color of @a n are the same.
  inline bool
  operator==(RBNode *n, RBNode::Color c)
  {
    return c == (n ? n->getColor() : RBNode::BLACK);
  }
  /// Equality.
  /// @note If @a n is @c NULL it is treated as having the color @c BLACK.
  /// @return @c true if @a c and the color of @a n are the same.
  inline bool
  operator==(RBNode::Color c, RBNode *n)
  {
    return n == c;
  }

  RBNode *
  RBNode::getChild(Direction d) const
  {
    return d == RIGHT ? _right : d == LEFT ? _left : nullptr;
  }

  RBNode *
  RBNode::rotate(Direction d)
  {
    self *parent        = _parent; // Cache because it can change before we use it.
    Direction child_dir = _parent ? _parent->getChildDirection(this) : NONE;
    Direction other_dir = this->flip(d);
    self *child         = this;

    if (d != NONE && this->getChild(other_dir)) {
      child = this->getChild(other_dir);
      this->clearChild(other_dir);
      this->setChild(child->getChild(d), other_dir);
      child->clearChild(d);
      child->setChild(this, d);
      child->structureFixup();
      this->structureFixup();
      if (parent) {
        parent->clearChild(child_dir);
        parent->setChild(child, child_dir);
      } else {
        child->_parent = nullptr;
      }
    }
    return child;
  }

  RBNode *
  RBNode::setChild(self *n, Direction d)
  {
    if (n) {
      n->_parent = this;
    }
    if (d == RIGHT) {
      _right = n;
    } else if (d == LEFT) {
      _left = n;
    }
    return n;
  }

  // Returns the root node
  RBNode *
  RBNode::rippleStructureFixup()
  {
    self *root = this; // last node seen, root node at the end
    self *p    = this;
    while (p) {
      p->structureFixup();
      root = p;
      p    = root->_parent;
    }
    return root;
  }

  void
  RBNode::replaceWith(self *n)
  {
    n->_color = _color;
    if (_parent) {
      Direction d = _parent->getChildDirection(this);
      _parent->setChild(nullptr, d);
      if (_parent != n) {
        _parent->setChild(n, d);
      }
    } else {
      n->_parent = nullptr;
    }
    n->_left = n->_right = nullptr;
    if (_left && _left != n) {
      n->setChild(_left, LEFT);
    }
    if (_right && _right != n) {
      n->setChild(_right, RIGHT);
    }
    _left = _right = nullptr;
  }

  /* Rebalance the tree. This node is the unbalanced node. */
  RBNode *
  RBNode::rebalanceAfterInsert()
  {
    self *x(this); // the node with the imbalance

    while (x && x->_parent == RED) {
      Direction child_dir = NONE;

      if (x->_parent->_parent) {
        child_dir = x->_parent->_parent->getChildDirection(x->_parent);
      } else {
        break;
      }
      Direction other_dir(flip(child_dir));

      self *y = x->_parent->_parent->getChild(other_dir);
      if (y == RED) {
        x->_parent->_color = BLACK;
        y->_color          = BLACK;
        x                  = x->_parent->_parent;
        x->_color          = RED;
      } else {
        if (x->_parent->getChild(other_dir) == x) {
          x = x->_parent;
          x->rotate(child_dir);
        }
        // Note setting the parent color to BLACK causes the loop to exit.
        x->_parent->_color          = BLACK;
        x->_parent->_parent->_color = RED;
        x->_parent->_parent->rotate(other_dir);
      }
    }

    // every node above this one has a subtree structure change,
    // so notify it. serendipitously, this makes it easy to return
    // the new root node.
    self *root   = this->rippleStructureFixup();
    root->_color = BLACK;

    return root;
  }

  // Returns new root node
  RBNode *
  RBNode::remove()
  {
    self *root = nullptr; // new root node, returned to caller

    /*  Handle two special cases first.
        - This is the only node in the tree, return a new root of NIL
        - This is the root node with only one child, return that child as new root
    */
    if (!_parent && !(_left && _right)) {
      if (_left) {
        _left->_parent = nullptr;
        root           = _left;
        root->_color   = BLACK;
      } else if (_right) {
        _right->_parent = nullptr;
        root            = _right;
        root->_color    = BLACK;
      } // else that was the only node, so leave @a root @c NULL.
      return root;
    }

    /*  The node to be removed from the tree.
        If @c this (the target node) has both children, we remove
        its successor, which cannot have a left child and
        put that node in place of the target node. Otherwise this
        node has at most one child, so we can remove it.
        Note that the successor of a node with a right child is always
        a right descendant of the node. Therefore, remove_node
        is an element of the tree rooted at this node.
        Because of the initial special case checks, we know
        that remove_node is @b not the root node.
    */
    self *remove_node(_left && _right ? _right->leftmostDescendant() : this);

    // This is the color of the node physically removed from the tree.
    // Normally this is the color of @a remove_node
    Color remove_color = remove_node->_color;
    // Need to remember the direction from @a remove_node to @a splice_node
    Direction d(NONE);

    // The child node that will be promoted to replace the removed node.
    // The choice of left or right is irrelevant, as remove_node has at
    // most one child (and splice_node may be NIL if remove_node has no
    // children).
    self *splice_node(remove_node->_left ? remove_node->_left : remove_node->_right);

    if (splice_node) {
      // @c replace_with copies color so in this case the actual color
      // lost is that of the splice_node.
      remove_color = splice_node->_color;
      remove_node->replaceWith(splice_node);
    } else {
      // No children on remove node so we can just clip it off the tree
      // We update splice_node to maintain the invariant that it is
      // the node where the physical removal occurred.
      splice_node = remove_node->_parent;
      // Keep @a d up to date.
      d = splice_node->getChildDirection(remove_node);
      splice_node->setChild(nullptr, d);
    }

    // If the node to pull out of the tree isn't this one,
    // then replace this node in the tree with that removed
    // node in liu of copying the data over.
    if (remove_node != this) {
      // Don't leave @a splice_node referring to a removed node
      if (splice_node == this) {
        splice_node = remove_node;
      }
      this->replaceWith(remove_node);
    }

    root         = splice_node->rebalanceAfterRemove(remove_color, d);
    root->_color = BLACK;
    return root;
  }

  /**
   * Rebalance tree after a deletion
   * Called on the spliced in node or its parent, whichever is not NIL.
   * This modifies the tree structure only if @a c is @c BLACK.
   */
  RBNode *
  RBNode::rebalanceAfterRemove(Color c,    //!< The color of the removed node
                               Direction d //!< Direction of removed node from its parent
  )
  {
    self *root;

    if (BLACK == c) { // only rebalance if too much black
      self *n      = this;
      self *parent = n->_parent;

      // If @a direction is set, then we need to start at a leaf pseudo-node.
      // This is why we need @a parent, otherwise we could just use @a n.
      if (NONE != d) {
        parent = n;
        n      = nullptr;
      }

      while (parent) { // @a n is not the root
        // If the current node is RED, we can just recolor and be done
        if (n && n == RED) {
          n->_color = BLACK;
          break;
        } else {
          // Parameterizing the rebalance logic on the directions. We
          // write for the left child case and flip directions for the
          // right child case
          Direction near(LEFT), far(RIGHT);
          if ((NONE == d && parent->getChildDirection(n) == RIGHT) || RIGHT == d) {
            near = RIGHT;
            far  = LEFT;
          }

          self *w = parent->getChild(far); // sibling(n)

          if (w->_color == RED) {
            w->_color      = BLACK;
            parent->_color = RED;
            parent->rotate(near);
            w = parent->getChild(far);
          }

          self *wfc = w->getChild(far);
          if (w->getChild(near) == BLACK && wfc == BLACK) {
            w->_color = RED;
            n         = parent;
            parent    = n->_parent;
            d         = NONE; // Cancel any leaf node logic
          } else {
            if (wfc->_color == BLACK) {
              w->getChild(near)->_color = BLACK;
              w->_color                 = RED;
              w->rotate(far);
              w   = parent->getChild(far);
              wfc = w->getChild(far); // w changed, update far child cache.
            }
            w->_color      = parent->_color;
            parent->_color = BLACK;
            wfc->_color    = BLACK;
            parent->rotate(near);
            break;
          }
        }
      }
    }
    root = this->rippleStructureFixup();
    return root;
  }

  /** Ensure that the local information associated with each node is
      correct globally This should only be called on debug builds as it
      breaks any efficiencies we have gained from our tree structure.
      */
  int
  RBNode::validate()
  {
#if 0
  int black_ht = 0;
  int black_ht1, black_ht2;

  if (_left) {
    black_ht1 = _left->validate();
  }
  else
    black_ht1 = 1;

  if (black_ht1 > 0 && _right)
    black_ht2 = _right->validate();
  else
    black_ht2 = 1;

  if (black_ht1 == black_ht2) {
    black_ht = black_ht1;
    if (this->_color == BLACK)
      ++black_ht;
    else {  // No red-red
      if (_left == RED)
        black_ht = 0;
      else if (_right == RED)
        black_ht = 0;
      if (black_ht == 0)
        std::cout << "Red-red child\n";
    }
  } else {
    std::cout << "Height mismatch " << black_ht1 << " " << black_ht2 << "\n";
  }
  if (black_ht > 0 && !this->structureValidate())
    black_ht = 0;

  return black_ht;
#else
    return 0;
#endif
  }
} // namespace detail
} // namespace ts
<|endoftext|>


<commit_before>/***************************************************************************
**
** This file is part of the qmlogre example on http://qt.gitorious.org.
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
**
** All rights reserved.
** Contact:  Nokia Corporation (qt-info@nokia.com)
**
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
**
**  * Redistributions of source code must retain the above copyright notice,
**    this list of conditions and the following disclaimer.
**  * Redistributions in binary form must reproduce the above copyright notice,
**    this list of conditions and the following disclaimer in the documentation
**    and/or other materials provided with ** the distribution.
**  * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the
**    names of its contributors may be used to endorse or promote products
**    derived from this software without specific ** prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
**************************************************************************/

#include <RenderSystems/GL/OgreGLTexture.h>
#include <RenderSystems/GL/OgreGLFrameBufferObject.h>
#include <RenderSystems/GL/OgreGLFBORenderTexture.h>

#include "ogrenode.h"

#include <Ogre.h>

#include <QtCore/QCoreApplication>
#include <QtCore/QDir>
#include <QSurfaceFormat>
#include <QOpenGLContext>
#include <QOpenGLFunctions>

OgreNode::OgreNode()
    : QSGGeometryNode()
    , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)
    , m_texture(0)
    , m_renderTexture(0)
    , m_ogreFBO(0)
    , m_dirtyFBO(false)
{
    setMaterial(&m_material);
    setOpaqueMaterial(&m_materialO);
    setGeometry(&m_geometry);
    setFlag(UsePreprocess);
}

OgreNode::~OgreNode()
{
    if (m_renderTexture) {
        m_renderTexture->removeAllViewports();
    }
}

void OgreNode::setOgreEngineItem(OgreEngineItem *ogreRootItem)
{
    m_ogreEngineItem = ogreRootItem;
}

void OgreNode::doneOgreContext()
{
    m_ogreEngineItem->doneOgreContext();
}

void OgreNode::activateOgreContext()
{
    m_ogreEngineItem->activateOgreContext();
    m_ogreEngineItem->ogreContext()->functions()->glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_ogreFBO);
}

GLuint OgreNode::getOgreFBO()
{
    if (!m_renderTexture)
        return 0;

    Ogre::GLFrameBufferObject *ogreFbo = 0;
    m_renderTexture->getCustomAttribute("FBO", &ogreFbo);
    Ogre::GLFBOManager *manager = ogreFbo->getManager();
    manager->bind(m_renderTexture);

    GLint id;
    glGetIntegerv(GL_FRAMEBUFFER_BINDING, &id);

    return id;
}

void OgreNode::preprocess()
{
    activateOgreContext();
    m_renderTexture->update(true);
    doneOgreContext();
}

void OgreNode::update()
{
    if (m_dirtyFBO) {
        activateOgreContext();
        updateFBO();
        m_ogreFBO = getOgreFBO();
        m_dirtyFBO = false;
        doneOgreContext();
    }
}

void OgreNode::updateFBO()
{
    if (m_renderTexture)
        Ogre::TextureManager::getSingleton().remove("RttTex");

    int samples = m_ogreEngineItem->ogreContext()->format().samples();
    rtt_texture = Ogre::TextureManager::getSingleton().createManual("RttTex",
                                                                    Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
                                                                    Ogre::TEX_TYPE_2D,
                                                                    m_size.width(),
                                                                    m_size.height(),
                                                                    0,
                                                                    Ogre::PF_R8G8B8A8,
                                                                    Ogre::TU_RENDERTARGET, 0, false,
                                                                    samples);

    m_renderTexture = rtt_texture->getBuffer()->getRenderTarget();

    m_renderTexture->addViewport(m_camera);
    m_renderTexture->getViewport(0)->setClearEveryFrame(true);
    m_renderTexture->getViewport(0)->setBackgroundColour(Ogre::ColourValue::Black);
    m_renderTexture->getViewport(0)->setOverlaysEnabled(false);

    Ogre::Real aspectRatio = Ogre::Real(m_size.width()) / Ogre::Real(m_size.height());
    m_camera->setAspectRatio(aspectRatio);

    QSGGeometry::updateTexturedRectGeometry(&m_geometry,
                                            QRectF(0, 0, m_size.width(), m_size.height()),
                                            QRectF(0, 0, 1, 1));

    Ogre::GLTexture *nativeTexture = static_cast<Ogre::GLTexture *>(rtt_texture.get());

    delete m_texture;
    m_texture = m_ogreEngineItem->createTextureFromId(nativeTexture->getGLID(), m_size);

    m_material.setTexture(m_texture);
    m_materialO.setTexture(m_texture);
}

void OgreNode::setSize(const QSize &size)
{
    if (size == m_size)
        return;

    m_size = size;
    m_dirtyFBO = true;
    markDirty(DirtyGeometry);
}
<commit_msg>Fixed pointer initialization.<commit_after>/***************************************************************************
**
** This file is part of the qmlogre example on http://qt.gitorious.org.
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).*
**
** All rights reserved.
** Contact:  Nokia Corporation (qt-info@nokia.com)
**
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
**
**  * Redistributions of source code must retain the above copyright notice,
**    this list of conditions and the following disclaimer.
**  * Redistributions in binary form must reproduce the above copyright notice,
**    this list of conditions and the following disclaimer in the documentation
**    and/or other materials provided with ** the distribution.
**  * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the
**    names of its contributors may be used to endorse or promote products
**    derived from this software without specific ** prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
**************************************************************************/

#include <RenderSystems/GL/OgreGLTexture.h>
#include <RenderSystems/GL/OgreGLFrameBufferObject.h>
#include <RenderSystems/GL/OgreGLFBORenderTexture.h>

#include "ogrenode.h"

#include <Ogre.h>

#include <QtCore/QCoreApplication>
#include <QtCore/QDir>
#include <QSurfaceFormat>
#include <QOpenGLContext>
#include <QOpenGLFunctions>

OgreNode::OgreNode()
    : QSGGeometryNode()
    , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)
    , m_texture(0)
    , m_ogreEngineItem(0)
    , m_camera(0)
    , m_renderTexture(0)
    , m_viewport(0)
    , m_window(0)
    , m_ogreFBO(0)
    , m_dirtyFBO(false)
{
    setMaterial(&m_material);
    setOpaqueMaterial(&m_materialO);
    setGeometry(&m_geometry);
    setFlag(UsePreprocess);
}

OgreNode::~OgreNode()
{
    if (m_renderTexture) {
        m_renderTexture->removeAllViewports();
    }
}

void OgreNode::setOgreEngineItem(OgreEngineItem *ogreRootItem)
{
    m_ogreEngineItem = ogreRootItem;
}

void OgreNode::doneOgreContext()
{
    m_ogreEngineItem->doneOgreContext();
}

void OgreNode::activateOgreContext()
{
    m_ogreEngineItem->activateOgreContext();
    m_ogreEngineItem->ogreContext()->functions()->glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_ogreFBO);
}

GLuint OgreNode::getOgreFBO()
{
    if (!m_renderTexture)
        return 0;

    Ogre::GLFrameBufferObject *ogreFbo = 0;
    m_renderTexture->getCustomAttribute("FBO", &ogreFbo);
    Ogre::GLFBOManager *manager = ogreFbo->getManager();
    manager->bind(m_renderTexture);

    GLint id;
    glGetIntegerv(GL_FRAMEBUFFER_BINDING, &id);

    return id;
}

void OgreNode::preprocess()
{
    activateOgreContext();
    m_renderTexture->update(true);
    doneOgreContext();
}

void OgreNode::update()
{
    if (m_dirtyFBO) {
        activateOgreContext();
        updateFBO();
        m_ogreFBO = getOgreFBO();
        m_dirtyFBO = false;
        doneOgreContext();
    }
}

void OgreNode::updateFBO()
{
    if (m_renderTexture)
        Ogre::TextureManager::getSingleton().remove("RttTex");

    int samples = m_ogreEngineItem->ogreContext()->format().samples();
    rtt_texture = Ogre::TextureManager::getSingleton().createManual("RttTex",
                                                                    Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
                                                                    Ogre::TEX_TYPE_2D,
                                                                    m_size.width(),
                                                                    m_size.height(),
                                                                    0,
                                                                    Ogre::PF_R8G8B8A8,
                                                                    Ogre::TU_RENDERTARGET, 0, false,
                                                                    samples);

    m_renderTexture = rtt_texture->getBuffer()->getRenderTarget();

    m_renderTexture->addViewport(m_camera);
    m_renderTexture->getViewport(0)->setClearEveryFrame(true);
    m_renderTexture->getViewport(0)->setBackgroundColour(Ogre::ColourValue::Black);
    m_renderTexture->getViewport(0)->setOverlaysEnabled(false);

    Ogre::Real aspectRatio = Ogre::Real(m_size.width()) / Ogre::Real(m_size.height());
    m_camera->setAspectRatio(aspectRatio);

    QSGGeometry::updateTexturedRectGeometry(&m_geometry,
                                            QRectF(0, 0, m_size.width(), m_size.height()),
                                            QRectF(0, 0, 1, 1));

    Ogre::GLTexture *nativeTexture = static_cast<Ogre::GLTexture *>(rtt_texture.get());

    delete m_texture;
    m_texture = m_ogreEngineItem->createTextureFromId(nativeTexture->getGLID(), m_size);

    m_material.setTexture(m_texture);
    m_materialO.setTexture(m_texture);
}

void OgreNode::setSize(const QSize &size)
{
    if (size == m_size)
        return;

    m_size = size;
    m_dirtyFBO = true;
    markDirty(DirtyGeometry);
}
<|endoftext|>


<commit_before>/******************************************************************************\
 *           ___        __                                                    *
 *          /\_ \    __/\ \                                                   *
 *          \//\ \  /\_\ \ \____    ___   _____   _____      __               *
 *            \ \ \ \/\ \ \ '__`\  /'___\/\ '__`\/\ '__`\  /'__`\             *
 *             \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_           *
 *             /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\          *
 *             \/____/ \/_/\/___/  \/____/ \ \ \/  \ \ \/  \/__/\/_/          *
 *                                          \ \_\   \ \_\                     *
 *                                           \/_/    \/_/                     *
 *                                                                            *
 * Copyright (C) 2011, 2012                                                   *
 * Dominik Charousset <dominik.charousset@haw-hamburg.de>                     *
 *                                                                            *
 * This file is part of libcppa.                                              *
 * libcppa 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 3 of the License                  *
 * or (at your option) any later version.                                     *
 *                                                                            *
 * libcppa 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 libcppa. If not, see <http://www.gnu.org/licenses/>.            *
\******************************************************************************/

#ifndef OPTION_HPP
#define OPTION_HPP

#include <new>
#include <utility>
#include "cppa/config.hpp"

namespace cppa {

/**
 * @brief Represents an optional value of @p T.
 */
template<typename T>
class option
{

 public:

    /**
     * @brief Typdef for @p T.
     */
    typedef T value_type;

    /**
     * @brief Default constructor.
     * @post <tt>valid() == false</tt>
     */
    option() : m_valid(false) { }

    /**
     * @brief Creates an @p option from @p value.
     * @post <tt>valid() == true</tt>
     */
    option(T&& value) : m_valid(false) { cr(std::move(value)); }

    /**
     * @brief Creates an @p option from @p value.
     * @post <tt>valid() == true</tt>
     */
    option(T const& value) : m_valid(false) { cr(value); }

    option(option const& other) : m_valid(false)
    {
        if (other.m_valid) cr(other.m_value);
    }

    option(option&& other) : m_valid(false)
    {
        if (other.m_valid) cr(std::move(other.m_value));
    }

    ~option() { destroy(); }

    option& operator=(option const& other)
    {
        if (m_valid)
        {
            if (other.m_valid) m_value = other.m_value;
            else destroy();
        }
        else if (other.m_valid)
        {
            cr(other.m_value);
        }
        return *this;
    }

    option& operator=(option&& other)
    {
        if (m_valid)
        {
            if (other.m_valid) m_value = std::move(other.m_value);
            else destroy();
        }
        else if (other.m_valid)
        {
            cr(std::move(other.m_value));
        }
        return *this;
    }

    option& operator=(T const& value)
    {
        if (m_valid) m_value = value;
        else cr(value);
        return *this;
    }

    option& operator=(T& value)
    {
        if (m_valid) m_value = std::move(value);
        else cr(std::move(value));
        return *this;
    }

    /**
     * @brief Returns @p true if this @p option has a valid value;
     *        otherwise @p false.
     */
    inline bool valid() const { return m_valid; }

    /**
     * @copydoc valid()
     */
    inline explicit operator bool() const { return m_valid; }

    /**
     * @brief Returns <tt>!valid()</tt>
     */
    inline bool operator!() const { return !m_valid; }

    /**
     * @brief Returns the value.
     */
    inline T& operator*()
    {
        CPPA_REQUIRE(valid());
        return m_value;
    }

    /**
     * @brief Returns the value.
     */
    inline T const& operator*() const
    {
        CPPA_REQUIRE(valid());
        return m_value;
    }

    /**
     * @brief Returns the value.
     */
    inline T& get()
    {
        CPPA_REQUIRE(valid());
        return m_value;
    }

    /**
     * @brief Returns the value.
     */
    inline T const& get() const
    {
        CPPA_REQUIRE(valid());
        return m_value;
    }

    /**
     * @brief Returns the value. The value is set to @p default_value
     *        if <tt>valid() == false</tt>.
     * @post <tt>valid() == true</tt>
     */
    inline T& get_or_else(T const& default_value)
    {
        if (!m_valid) cr(default_value);
        return m_value;
    }

    /**
     * @copydoc get_or_else(T const&)
     */
    inline T& get_or_else(T&& default_value)
    {
        if (!m_valid) cr(std::move(default_value));
        return m_value;
    }

 private:

    bool m_valid;
    union { T m_value; };

    void destroy()
    {
        if (m_valid)
        {
            m_value.~T();
            m_valid = false;
        }
    }

    template<typename V>
    void cr(V&& value)
    {
        CPPA_REQUIRE(!valid());
        m_valid = true;
        new (&m_value) T (std::forward<V>(value));
    }

};

/** @relates option */
template<typename T, typename U>
bool operator==(option<T> const& lhs, option<U> const& rhs)
{
    if ((lhs) && (rhs)) return *lhs == *rhs;
    return false;
}

/** @relates option */
template<typename T, typename U>
bool operator==(option<T> const& lhs, U const& rhs)
{
    if (lhs) return *lhs == rhs;
    return false;
}

/** @relates option */
template<typename T, typename U>
bool operator==(T const& lhs, option<U> const& rhs)
{
    return rhs == lhs;
}

/** @relates option */
template<typename T, typename U>
bool operator!=(option<T> const& lhs, option<U> const& rhs)
{
    return !(lhs == rhs);
}

/** @relates option */
template<typename T, typename U>
bool operator!=(option<T> const& lhs, U const& rhs)
{
    return !(lhs == rhs);
}

/** @relates option */
template<typename T, typename U>
bool operator!=(T const& lhs, option<U> const& rhs)
{
    return !(lhs == rhs);
}

} // namespace cppa

#endif // OPTION_HPP
<commit_msg>made get_or_else const<commit_after>/******************************************************************************\
 *           ___        __                                                    *
 *          /\_ \    __/\ \                                                   *
 *          \//\ \  /\_\ \ \____    ___   _____   _____      __               *
 *            \ \ \ \/\ \ \ '__`\  /'___\/\ '__`\/\ '__`\  /'__`\             *
 *             \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_           *
 *             /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\          *
 *             \/____/ \/_/\/___/  \/____/ \ \ \/  \ \ \/  \/__/\/_/          *
 *                                          \ \_\   \ \_\                     *
 *                                           \/_/    \/_/                     *
 *                                                                            *
 * Copyright (C) 2011, 2012                                                   *
 * Dominik Charousset <dominik.charousset@haw-hamburg.de>                     *
 *                                                                            *
 * This file is part of libcppa.                                              *
 * libcppa 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 3 of the License                  *
 * or (at your option) any later version.                                     *
 *                                                                            *
 * libcppa 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 libcppa. If not, see <http://www.gnu.org/licenses/>.            *
\******************************************************************************/

#ifndef OPTION_HPP
#define OPTION_HPP

#include <new>
#include <utility>
#include "cppa/config.hpp"

namespace cppa {

/**
 * @brief Represents an optional value of @p T.
 */
template<typename T>
class option
{

 public:

    /**
     * @brief Typdef for @p T.
     */
    typedef T type;

    /**
     * @brief Default constructor.
     * @post <tt>valid() == false</tt>
     */
    option() : m_valid(false) { }

    /**
     * @brief Creates an @p option from @p value.
     * @post <tt>valid() == true</tt>
     */
    option(T value) : m_valid(false) { cr(std::move(value)); }

    option(option const& other) : m_valid(false)
    {
        if (other.m_valid) cr(other.m_value);
    }

    option(option&& other) : m_valid(false)
    {
        if (other.m_valid) cr(std::move(other.m_value));
    }

    ~option() { destroy(); }

    option& operator=(option const& other)
    {
        if (m_valid)
        {
            if (other.m_valid) m_value = other.m_value;
            else destroy();
        }
        else if (other.m_valid)
        {
            cr(other.m_value);
        }
        return *this;
    }

    option& operator=(option&& other)
    {
        if (m_valid)
        {
            if (other.m_valid) m_value = std::move(other.m_value);
            else destroy();
        }
        else if (other.m_valid)
        {
            cr(std::move(other.m_value));
        }
        return *this;
    }

    option& operator=(T const& value)
    {
        if (m_valid) m_value = value;
        else cr(value);
        return *this;
    }

    option& operator=(T& value)
    {
        if (m_valid) m_value = std::move(value);
        else cr(std::move(value));
        return *this;
    }

    /**
     * @brief Returns @p true if this @p option has a valid value;
     *        otherwise @p false.
     */
    inline bool valid() const { return m_valid; }

    inline bool empty() const { return !m_valid; }

    /**
     * @copydoc valid()
     */
    inline explicit operator bool() const { return valid(); }

    /**
     * @brief Returns <tt>!valid()</tt>
     */
    inline bool operator!() const { return empty(); }

    /**
     * @brief Returns the value.
     */
    inline T& operator*()
    {
        CPPA_REQUIRE(valid());
        return m_value;
    }

    /**
     * @brief Returns the value.
     */
    inline T const& operator*() const
    {
        CPPA_REQUIRE(valid());
        return m_value;
    }

    /**
     * @brief Returns the value.
     */
    inline T& get()
    {
        CPPA_REQUIRE(valid());
        return m_value;
    }

    /**
     * @brief Returns the value.
     */
    inline T const& get() const
    {
        CPPA_REQUIRE(valid());
        return m_value;
    }

    /**
     * @brief Returns the value. The value is set to @p default_value
     *        if <tt>valid() == false</tt>.
     * @post <tt>valid() == true</tt>
     */
    inline const T& get_or_else(const T& default_value) const
    {
        if (valid()) return get();
        return default_value;
    }

 private:

    bool m_valid;
    union { T m_value; };

    void destroy()
    {
        if (m_valid)
        {
            m_value.~T();
            m_valid = false;
        }
    }

    template<typename V>
    void cr(V&& value)
    {
        CPPA_REQUIRE(!valid());
        m_valid = true;
        new (&m_value) T (std::forward<V>(value));
    }

};

/** @relates option */
template<typename T, typename U>
bool operator==(option<T> const& lhs, option<U> const& rhs)
{
    if ((lhs) && (rhs)) return *lhs == *rhs;
    return false;
}

/** @relates option */
template<typename T, typename U>
bool operator==(option<T> const& lhs, U const& rhs)
{
    if (lhs) return *lhs == rhs;
    return false;
}

/** @relates option */
template<typename T, typename U>
bool operator==(T const& lhs, option<U> const& rhs)
{
    return rhs == lhs;
}

/** @relates option */
template<typename T, typename U>
bool operator!=(option<T> const& lhs, option<U> const& rhs)
{
    return !(lhs == rhs);
}

/** @relates option */
template<typename T, typename U>
bool operator!=(option<T> const& lhs, U const& rhs)
{
    return !(lhs == rhs);
}

/** @relates option */
template<typename T, typename U>
bool operator!=(T const& lhs, option<U> const& rhs)
{
    return !(lhs == rhs);
}

} // namespace cppa

#endif // OPTION_HPP
<|endoftext|>