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

#include "txdb.h"

#include "core.h"
#include "pow.h"
#include "uint256.h"

#include <stdint.h>

using namespace std;

void static BatchWriteCoins(CLevelDBBatch &batch, const uint256 &hash, const CCoins &coins) {
    if (coins.IsPruned())
        batch.Erase(make_pair('c', hash));
    else
        batch.Write(make_pair('c', hash), coins);
}

void static BatchWriteHashBestChain(CLevelDBBatch &batch, const uint256 &hash) {
    batch.Write('B', hash);
}

CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe) {
}

bool CCoinsViewDB::GetCoins(const uint256 &txid, CCoins &coins) {
    return db.Read(make_pair('c', txid), coins);
}

bool CCoinsViewDB::SetCoins(const uint256 &txid, const CCoins &coins) {
    CLevelDBBatch batch;
    BatchWriteCoins(batch, txid, coins);
    return db.WriteBatch(batch);
}

bool CCoinsViewDB::HaveCoins(const uint256 &txid) {
    return db.Exists(make_pair('c', txid));
}

uint256 CCoinsViewDB::GetBestBlock() {
    uint256 hashBestChain;
    if (!db.Read('B', hashBestChain))
        return uint256(0);
    return hashBestChain;
}

bool CCoinsViewDB::SetBestBlock(const uint256 &hashBlock) {
    CLevelDBBatch batch;
    BatchWriteHashBestChain(batch, hashBlock);
    return db.WriteBatch(batch);
}

bool CCoinsViewDB::BatchWrite(const CCoinsMap &mapCoins, const uint256 &hashBlock) {
    LogPrint("coindb", "Committing %u changed transactions to coin database...\n", (unsigned int)mapCoins.size());

    CLevelDBBatch batch;
    for (CCoinsMap::const_iterator it = mapCoins.begin(); it != mapCoins.end(); it++)
        BatchWriteCoins(batch, it->first, it->second);
    if (hashBlock != uint256(0))
        BatchWriteHashBestChain(batch, hashBlock);

    return db.WriteBatch(batch);
}

CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CLevelDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) {
}

bool CBlockTreeDB::WriteBlockIndex(const CDiskBlockIndex& blockindex)
{
    return Write(make_pair('b', blockindex.GetBlockHash()), blockindex);
}

bool CBlockTreeDB::WriteBlockFileInfo(int nFile, const CBlockFileInfo &info) {
    return Write(make_pair('f', nFile), info);
}

bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {
    return Read(make_pair('f', nFile), info);
}

bool CBlockTreeDB::WriteLastBlockFile(int nFile) {
    return Write('l', nFile);
}

bool CBlockTreeDB::WriteReindexing(bool fReindexing) {
    if (fReindexing)
        return Write('R', '1');
    else
        return Erase('R');
}

bool CBlockTreeDB::ReadReindexing(bool &fReindexing) {
    fReindexing = Exists('R');
    return true;
}

bool CBlockTreeDB::ReadLastBlockFile(int &nFile) {
    return Read('l', nFile);
}

bool CCoinsViewDB::GetStats(CCoinsStats &stats) {
    leveldb::Iterator *pcursor = db.NewIterator();
    pcursor->SeekToFirst();

    CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
    stats.hashBlock = GetBestBlock();
    ss << stats.hashBlock;
    int64_t nTotalAmount = 0;
    while (pcursor->Valid()) {
        boost::this_thread::interruption_point();
        try {
            leveldb::Slice slKey = pcursor->key();
            CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
            char chType;
            ssKey >> chType;
            if (chType == 'c') {
                leveldb::Slice slValue = pcursor->value();
                CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
                CCoins coins;
                ssValue >> coins;
                uint256 txhash;
                ssKey >> txhash;
                ss << txhash;
                ss << VARINT(coins.nVersion);
                ss << (coins.fCoinBase ? 'c' : 'n');
                ss << VARINT(coins.nHeight);
                stats.nTransactions++;
                for (unsigned int i=0; i<coins.vout.size(); i++) {
                    const CTxOut &out = coins.vout[i];
                    if (!out.IsNull()) {
                        stats.nTransactionOutputs++;
                        ss << VARINT(i+1);
                        ss << out;
                        nTotalAmount += out.nValue;
                    }
                }
                stats.nSerializedSize += 32 + slValue.size();
                ss << VARINT(0);
            }
            pcursor->Next();
        } catch (std::exception &e) {
            return error("%s : Deserialize or I/O error - %s", __func__, e.what());
        }
    }
    delete pcursor;
    stats.nHeight = mapBlockIndex.find(GetBestBlock())->second->nHeight;
    stats.hashSerialized = ss.GetHash();
    stats.nTotalAmount = nTotalAmount;
    return true;
}

bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) {
    return Read(make_pair('t', txid), pos);
}

bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> >&vect) {
    CLevelDBBatch batch;
    for (std::vector<std::pair<uint256,CDiskTxPos> >::const_iterator it=vect.begin(); it!=vect.end(); it++)
        batch.Write(make_pair('t', it->first), it->second);
    return WriteBatch(batch);
}

bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
    return Write(std::make_pair('F', name), fValue ? '1' : '0');
}

bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) {
    char ch;
    if (!Read(std::make_pair('F', name), ch))
        return false;
    fValue = ch == '1';
    return true;
}

bool CBlockTreeDB::LoadBlockIndexGuts()
{
    leveldb::Iterator *pcursor = NewIterator();

    CDataStream ssKeySet(SER_DISK, CLIENT_VERSION);
    ssKeySet << make_pair('b', uint256(0));
    pcursor->Seek(ssKeySet.str());

    // Load mapBlockIndex
    while (pcursor->Valid()) {
        boost::this_thread::interruption_point();
        try {
            leveldb::Slice slKey = pcursor->key();
            CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
            char chType;
            ssKey >> chType;
            if (chType == 'b') {
                leveldb::Slice slValue = pcursor->value();
                CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
                CDiskBlockIndex diskindex;
                ssValue >> diskindex;

                // Construct block index object
                CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
                pindexNew->pprev          = InsertBlockIndex(diskindex.hashPrev);
                pindexNew->nHeight        = diskindex.nHeight;
                pindexNew->nFile          = diskindex.nFile;
                pindexNew->nDataPos       = diskindex.nDataPos;
                pindexNew->nUndoPos       = diskindex.nUndoPos;
                pindexNew->nVersion       = diskindex.nVersion;
                pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
                pindexNew->nTime          = diskindex.nTime;
                pindexNew->nBits          = diskindex.nBits;
                pindexNew->nNonce         = diskindex.nNonce;
                pindexNew->nStatus        = diskindex.nStatus;
                pindexNew->nTx            = diskindex.nTx;

                if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits))
                    return error("LoadBlockIndex() : CheckProofOfWork failed: %s", pindexNew->ToString());

                pcursor->Next();
            } else {
                break; // if shutdown requested or finished loading block index
            }
        } catch (std::exception &e) {
            return error("%s : Deserialize or I/O error - %s", __func__, e.what());
        }
    }
    delete pcursor;

    return true;
}
<commit_msg>Changed LevelDB cursors to use scoped pointers to ensure destruction when going out of scope.<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "txdb.h"

#include "core.h"
#include "pow.h"
#include "uint256.h"

#include <stdint.h>

using namespace std;

void static BatchWriteCoins(CLevelDBBatch &batch, const uint256 &hash, const CCoins &coins) {
    if (coins.IsPruned())
        batch.Erase(make_pair('c', hash));
    else
        batch.Write(make_pair('c', hash), coins);
}

void static BatchWriteHashBestChain(CLevelDBBatch &batch, const uint256 &hash) {
    batch.Write('B', hash);
}

CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe) {
}

bool CCoinsViewDB::GetCoins(const uint256 &txid, CCoins &coins) {
    return db.Read(make_pair('c', txid), coins);
}

bool CCoinsViewDB::SetCoins(const uint256 &txid, const CCoins &coins) {
    CLevelDBBatch batch;
    BatchWriteCoins(batch, txid, coins);
    return db.WriteBatch(batch);
}

bool CCoinsViewDB::HaveCoins(const uint256 &txid) {
    return db.Exists(make_pair('c', txid));
}

uint256 CCoinsViewDB::GetBestBlock() {
    uint256 hashBestChain;
    if (!db.Read('B', hashBestChain))
        return uint256(0);
    return hashBestChain;
}

bool CCoinsViewDB::SetBestBlock(const uint256 &hashBlock) {
    CLevelDBBatch batch;
    BatchWriteHashBestChain(batch, hashBlock);
    return db.WriteBatch(batch);
}

bool CCoinsViewDB::BatchWrite(const CCoinsMap &mapCoins, const uint256 &hashBlock) {
    LogPrint("coindb", "Committing %u changed transactions to coin database...\n", (unsigned int)mapCoins.size());

    CLevelDBBatch batch;
    for (CCoinsMap::const_iterator it = mapCoins.begin(); it != mapCoins.end(); it++)
        BatchWriteCoins(batch, it->first, it->second);
    if (hashBlock != uint256(0))
        BatchWriteHashBestChain(batch, hashBlock);

    return db.WriteBatch(batch);
}

CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CLevelDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) {
}

bool CBlockTreeDB::WriteBlockIndex(const CDiskBlockIndex& blockindex)
{
    return Write(make_pair('b', blockindex.GetBlockHash()), blockindex);
}

bool CBlockTreeDB::WriteBlockFileInfo(int nFile, const CBlockFileInfo &info) {
    return Write(make_pair('f', nFile), info);
}

bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {
    return Read(make_pair('f', nFile), info);
}

bool CBlockTreeDB::WriteLastBlockFile(int nFile) {
    return Write('l', nFile);
}

bool CBlockTreeDB::WriteReindexing(bool fReindexing) {
    if (fReindexing)
        return Write('R', '1');
    else
        return Erase('R');
}

bool CBlockTreeDB::ReadReindexing(bool &fReindexing) {
    fReindexing = Exists('R');
    return true;
}

bool CBlockTreeDB::ReadLastBlockFile(int &nFile) {
    return Read('l', nFile);
}

bool CCoinsViewDB::GetStats(CCoinsStats &stats) {
    boost::scoped_ptr<leveldb::Iterator> pcursor(db.NewIterator());
    pcursor->SeekToFirst();

    CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
    stats.hashBlock = GetBestBlock();
    ss << stats.hashBlock;
    int64_t nTotalAmount = 0;
    while (pcursor->Valid()) {
        boost::this_thread::interruption_point();
        try {
            leveldb::Slice slKey = pcursor->key();
            CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
            char chType;
            ssKey >> chType;
            if (chType == 'c') {
                leveldb::Slice slValue = pcursor->value();
                CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
                CCoins coins;
                ssValue >> coins;
                uint256 txhash;
                ssKey >> txhash;
                ss << txhash;
                ss << VARINT(coins.nVersion);
                ss << (coins.fCoinBase ? 'c' : 'n');
                ss << VARINT(coins.nHeight);
                stats.nTransactions++;
                for (unsigned int i=0; i<coins.vout.size(); i++) {
                    const CTxOut &out = coins.vout[i];
                    if (!out.IsNull()) {
                        stats.nTransactionOutputs++;
                        ss << VARINT(i+1);
                        ss << out;
                        nTotalAmount += out.nValue;
                    }
                }
                stats.nSerializedSize += 32 + slValue.size();
                ss << VARINT(0);
            }
            pcursor->Next();
        } catch (std::exception &e) {
            return error("%s : Deserialize or I/O error - %s", __func__, e.what());
        }
    }
    stats.nHeight = mapBlockIndex.find(GetBestBlock())->second->nHeight;
    stats.hashSerialized = ss.GetHash();
    stats.nTotalAmount = nTotalAmount;
    return true;
}

bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) {
    return Read(make_pair('t', txid), pos);
}

bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> >&vect) {
    CLevelDBBatch batch;
    for (std::vector<std::pair<uint256,CDiskTxPos> >::const_iterator it=vect.begin(); it!=vect.end(); it++)
        batch.Write(make_pair('t', it->first), it->second);
    return WriteBatch(batch);
}

bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
    return Write(std::make_pair('F', name), fValue ? '1' : '0');
}

bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) {
    char ch;
    if (!Read(std::make_pair('F', name), ch))
        return false;
    fValue = ch == '1';
    return true;
}

bool CBlockTreeDB::LoadBlockIndexGuts()
{
    boost::scoped_ptr<leveldb::Iterator> pcursor(NewIterator());

    CDataStream ssKeySet(SER_DISK, CLIENT_VERSION);
    ssKeySet << make_pair('b', uint256(0));
    pcursor->Seek(ssKeySet.str());

    // Load mapBlockIndex
    while (pcursor->Valid()) {
        boost::this_thread::interruption_point();
        try {
            leveldb::Slice slKey = pcursor->key();
            CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
            char chType;
            ssKey >> chType;
            if (chType == 'b') {
                leveldb::Slice slValue = pcursor->value();
                CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
                CDiskBlockIndex diskindex;
                ssValue >> diskindex;

                // Construct block index object
                CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
                pindexNew->pprev          = InsertBlockIndex(diskindex.hashPrev);
                pindexNew->nHeight        = diskindex.nHeight;
                pindexNew->nFile          = diskindex.nFile;
                pindexNew->nDataPos       = diskindex.nDataPos;
                pindexNew->nUndoPos       = diskindex.nUndoPos;
                pindexNew->nVersion       = diskindex.nVersion;
                pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
                pindexNew->nTime          = diskindex.nTime;
                pindexNew->nBits          = diskindex.nBits;
                pindexNew->nNonce         = diskindex.nNonce;
                pindexNew->nStatus        = diskindex.nStatus;
                pindexNew->nTx            = diskindex.nTx;

                if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits))
                    return error("LoadBlockIndex() : CheckProofOfWork failed: %s", pindexNew->ToString());

                pcursor->Next();
            } else {
                break; // if shutdown requested or finished loading block index
            }
        } catch (std::exception &e) {
            return error("%s : Deserialize or I/O error - %s", __func__, e.what());
        }
    }

    return true;
}
<|endoftext|>


<commit_before>/*
 * This is part of the FL library, a C++ Bayesian filtering library
 * (https://github.com/filtering-library)
 *
 * Copyright (c) 2014 Jan Issac (jan.issac@gmail.com)
 * Copyright (c) 2014 Manuel Wuthrich (manuel.wuthrich@gmail.com)
 *
 * Max-Planck Institute for Intelligent Systems, AMD Lab
 * University of Southern California, CLMC Lab
 *
 * This Source Code Form is subject to the terms of the MIT License (MIT).
 * A copy of the license can be found in the LICENSE file distributed with this
 * source code.
 */

/**
 * \file t_distribution.hpp
 * \date August 2015
 * \author Jan Issac (jan.issac@gmail.com)
 * \author Cristina Garcia Cifuentes (c.garciacifuentes@gmail.com)
 */

#ifndef FL__DISTRIBUTION__T_DISTRIBUTION_HPP
#define FL__DISTRIBUTION__T_DISTRIBUTION_HPP

#include <Eigen/Dense>

#include <random>
#include <boost/math/distributions.hpp>

#include <fl/util/meta.hpp>
#include <fl/util/types.hpp>
#include <fl/exception/exception.hpp>
#include <fl/distribution/gaussian.hpp>
#include <fl/distribution/chi_squared.hpp>
#include <fl/distribution/interface/evaluation.hpp>
#include <fl/distribution/interface/moments.hpp>
#include <fl/distribution/interface/standard_gaussian_mapping.hpp>

namespace fl
{

/**
 * \ingroup distributions
 *
 * \brief TDistribution represents a multivariate student's t-distribution
 * \f$t_\nu(\mu, \Sigma)\f$, where \f$\nu \in \mathbb{R} \f$ is the
 * degree-of-freedom, \f$\mu\in \mathbb{R}^n\f$ the distribution location and
 * \f$\Sigma \in \mathbb{R}^{n\times n} \f$ the scaling or covariance matrix.
 */
template <typename Variate>
class TDistribution
    : public Moments<Variate>,
      public Evaluation<Variate>,
      public StandardGaussianMapping<
                Variate,
                JoinSizes<SizeOf<Variate>::Value, 1>::Value>
{
private:
    typedef StandardGaussianMapping<
                Variate,
                JoinSizes<SizeOf<Variate>::Value, 1>::Value
            > StdGaussianMappingBase;

public:
    /**
     * \brief Second moment matrix type, i.e covariance matrix
     */
    typedef typename Moments<Variate>::SecondMoment SecondMoment;

    /**
     * \brief Represents the StandardGaussianMapping standard variate type which
     *        is of the same dimension as the \c TDistribution \c Variate. The
     *        StandardVariate type is used to sample from a standard normal
     *        Gaussian and map it to this \c TDistribution
     */
    typedef typename StdGaussianMappingBase::StandardVariate StandardVariate;

public:
    /**
     * Creates a dynamic or fixed size t-distribution.
     *
     * \param degrees_of_freedom
     *                  t-distribution degree-of-freedom
     * \param dimension Dimension of the distribution. The default is defined by
     *                  the dimension of the variable type \em Vector. If the
     *                  size of the Variate at compile time is fixed, this will
     *                  be adapted. For dynamic-sized Variable the dimension is
     *                  initialized to 0.
     */
    explicit TDistribution(Real degrees_of_freedom,
                           int dim = DimensionOf<Variate>())
        : chi2_(degrees_of_freedom),
          normal_(dim),
          StdGaussianMappingBase(dim + 1)
    {
        static_assert(Variate::SizeAtCompileTime != 0,
                      "Illegal static dimension");

        normal_.set_standard();
    }

    /**
     * \brief Overridable default destructor
     */
    virtual ~TDistribution() { }

    /**
     * \return a t-distribution sample of the type \c Variate determined by
     * mapping a standard normal sample into the t-distribution sample space
     *
     * \param sample    Standard normal sample
     *
     * \throws See Gaussian<Variate>::map_standard_normal
     */
    Variate map_standard_normal(const StandardVariate& sample) const override
    {
        assert(sample.size() == dimension() + 1);

        Real u = chi2_.map_standard_normal(sample.bottomRows(1)(0));
        Variate n = normal_.map_standard_normal(sample.topRows(dimension()));

        // rvo
        Variate v = location() + std::sqrt(degrees_of_freedom() / u) * n;
        return v;
    }

    /**
     * \return Log of the probability of the given sample \c variate
     *
     * Evaluates the t-distribution pdf
     *
     *  \f$ t_\nu(\mu, \Sigma) = \frac{\Gamma\left[(\nu+p)/2\right]}
     *          {\Gamma(\nu/2)
     *           \nu^{p/2}\pi^{p/2}
     *           \left|{\boldsymbol\Sigma}\right|^{1/2}
     *           \left[1 +
     *                 \frac{1}{\nu}
     *                 ({\mathbf x}-{\boldsymbol\mu})^T
     *                 {\boldsymbol\Sigma}^{-1}
     *                 ({\mathbf x}-{\boldsymbol\mu})\right]^{(\nu+p)/2}} \f$
     *
     * at location \f${\mathbf x}\f$
     *
     *
     * \param variate sample which should be evaluated
     *
     * \throws See Gaussian<Variate>::has_full_rank()
     */
    Real log_probability(const Variate& x) const override
    {
        return cached_log_pdf_.log_probability(*this, x);
    }

    /**
     * \return Gaussian dimension
     */
    virtual constexpr int dimension() const
    {
        return normal_.dimension();
    }

    /**
     * \return t-distribution location
     */
    const Variate& mean() const override
    {
        return location();
    }

    /**
     * \return t-distribution scaling matrix
     *
     * \throws See Gaussian<Variate>::covariance()
     */
    const SecondMoment& covariance() const override
    {
        return normal_.covariance();
    }

    /**
     * \return t-distribution location
     */
    virtual const Variate& location() const
    {
        return normal_.mean();
    }

    /**
     * \return t-distribution degree-of-freedom
     */
    virtual Real degrees_of_freedom() const
    {
        return chi2_.degrees_of_freedom();
    }

    /**
     * Changes the dimension of the dynamic-size t-distribution and sets it to a
     * standard distribution with zero mean and identity covariance.
     *
     * \param new_dimension New dimension of the t-distribution
     *
     * \throws ResizingFixedSizeEntityException
     *         see standard_variate_dimension(int)
     */
    virtual void dimension(int new_dimension)
    {
        StdGaussianMappingBase::standard_variate_dimension(new_dimension + 1);
        normal_.dimension(new_dimension);
        cached_log_pdf_.flag_dirty();
    }

    /**
     * Sets the distribution location
     *
     * \param location New t-distribution mean
     *
     * \throws WrongSizeException
     */
    virtual void location(const Variate& new_location) noexcept
    {
        normal_.mean(new_location);
        cached_log_pdf_.flag_dirty();
    }

    /**
     * Sets the covariance matrix
     * \param covariance New covariance matrix
     *
     * \throws WrongSizeException
     */

    virtual void scaling_matrix(const SecondMoment& scaling_matrix)
    {
        normal_.covariance(scaling_matrix);
        cached_log_pdf_.flag_dirty();
    }

    /**
     * Sets t-distribution degree-of-freedom
     */
    virtual void degrees_of_freedom(Real dof) const
    {
        chi2_.degrees_of_freedom(dof);
        cached_log_pdf_.flag_dirty();
    }

protected:
    /** \cond internal */
    ChiSquared chi2_;
    Gaussian<Variate> normal_;
    /** \endcond */

private:
    CachedLogPdf cached_log_pdf_;

private:
    class CachedLogPdf
    {
    public:
        CachedLogPdf()
            : dirty_(true)
        { }

        /**
         * Evaluates the t-distribution pdf at a given position \c x
         */
        Real log_probability(
                const TDistribution<Variate>& t_distr, const Variate& x)
        {
            if (dirty_) update(t_distr);

            Variate z = x - location();
            Real dof = t_distr.degrees_of_freedom();

            Real quad_term = (z.transpose() * t_distr.normal_.precision() * z);
            Real ln_term = std::log(Real(1) + quad_term  / dof);

            return const_term_ - const_factor_ * ln_term;
        }

        void flag_dirty() { dirty_ = true; }

    private:
        void update(const TDistribution<Variate>& t_distr)
        {
            Real half = Real(1)/Real(2);
            Real dim = t_distr.dimension();
            Real dof = t_distr.degrees_of_freedom();
            const_term_ =
                boost::lgamma(half * (dof + dim))
                - boost::lgamma(half * dof)
                - half * (dim * std::log(M_PI * dof))
                - half * (std::log(t_distr.normal_.determinant()));

            const_factor_ = half * (dof + dim);

            dirty_ = false;
        }

        bool dirty_;
        Real const_factor_;
        Real const_term_;
    };

    friend class CachedLogPdf;
};

}

#endif
<commit_msg>Updated TDistribution<commit_after>/*
 * This is part of the FL library, a C++ Bayesian filtering library
 * (https://github.com/filtering-library)
 *
 * Copyright (c) 2014 Jan Issac (jan.issac@gmail.com)
 * Copyright (c) 2014 Manuel Wuthrich (manuel.wuthrich@gmail.com)
 *
 * Max-Planck Institute for Intelligent Systems, AMD Lab
 * University of Southern California, CLMC Lab
 *
 * This Source Code Form is subject to the terms of the MIT License (MIT).
 * A copy of the license can be found in the LICENSE file distributed with this
 * source code.
 */

/**
 * \file t_distribution.hpp
 * \date August 2015
 * \author Jan Issac (jan.issac@gmail.com)
 * \author Cristina Garcia Cifuentes (c.garciacifuentes@gmail.com)
 */

#ifndef FL__DISTRIBUTION__T_DISTRIBUTION_HPP
#define FL__DISTRIBUTION__T_DISTRIBUTION_HPP

#include <Eigen/Dense>

#include <random>
#include <boost/math/distributions.hpp>

#include <fl/util/meta.hpp>
#include <fl/util/types.hpp>
#include <fl/exception/exception.hpp>
#include <fl/distribution/gaussian.hpp>
#include <fl/distribution/chi_squared.hpp>
#include <fl/distribution/interface/evaluation.hpp>
#include <fl/distribution/interface/moments.hpp>
#include <fl/distribution/interface/standard_gaussian_mapping.hpp>

namespace fl
{

/**
 * \ingroup distributions
 *
 * \brief TDistribution represents a multivariate student's t-distribution
 * \f$t_\nu(\mu, \Sigma)\f$, where \f$\nu \in \mathbb{R} \f$ is the
 * degree-of-freedom, \f$\mu\in \mathbb{R}^n\f$ the distribution location and
 * \f$\Sigma \in \mathbb{R}^{n\times n} \f$ the scaling or covariance matrix.
 */
template <typename Variate>
class TDistribution
    : public Moments<Variate>,
      public Evaluation<Variate>,
      public StandardGaussianMapping<
                Variate,
                JoinSizes<SizeOf<Variate>::Value, 1>::Value>
{
private:
    typedef StandardGaussianMapping<
                Variate,
                JoinSizes<SizeOf<Variate>::Value, 1>::Value
            > StdGaussianMappingBase;

public:
    /**
     * \brief Second moment matrix type, i.e covariance matrix
     */
    typedef typename Moments<Variate>::SecondMoment SecondMoment;

    /**
     * \brief Represents the StandardGaussianMapping standard variate type which
     *        is of the same dimension as the \c TDistribution \c Variate. The
     *        StandardVariate type is used to sample from a standard normal
     *        Gaussian and map it to this \c TDistribution
     */
    typedef typename StdGaussianMappingBase::StandardVariate StandardVariate;

public:
    /**
     * Creates a dynamic or fixed size t-distribution.
     *
     * \param degrees_of_freedom
     *                  t-distribution degree-of-freedom
     * \param dimension Dimension of the distribution. The default is defined by
     *                  the dimension of the variable type \em Vector. If the
     *                  size of the Variate at compile time is fixed, this will
     *                  be adapted. For dynamic-sized Variable the dimension is
     *                  initialized to 0.
     */
    explicit TDistribution(Real degrees_of_freedom,
                           int dim = DimensionOf<Variate>())
        : StdGaussianMappingBase(dim + 1),
          chi2_(degrees_of_freedom),
          normal_(dim)
    {
        static_assert(Variate::SizeAtCompileTime != 0,
                      "Illegal static dimension");

        normal_.set_standard();
    }

    /**
     * \brief Overridable default destructor
     */
    virtual ~TDistribution() { }

    /**
     * \return a t-distribution sample of the type \c Variate determined by
     * mapping a standard normal sample into the t-distribution sample space
     *
     * \param sample    Standard normal sample
     *
     * \throws See Gaussian<Variate>::map_standard_normal
     */
    Variate map_standard_normal(const StandardVariate& sample) const override
    {
        assert(sample.size() == dimension() + 1);

        Real u = chi2_.map_standard_normal(sample.bottomRows(1)(0));
        Variate n = normal_.map_standard_normal(sample.topRows(dimension()));

        // rvo
        Variate v = location() + std::sqrt(degrees_of_freedom() / u) * n;
        return v;
    }

    /**
     * \return Log of the probability of the given sample \c variate
     *
     * Evaluates the t-distribution pdf
     *
     *  \f$ t_\nu(\mu, \Sigma) = \frac{\Gamma\left[(\nu+p)/2\right]}
     *          {\Gamma(\nu/2)
     *           \nu^{p/2}\pi^{p/2}
     *           \left|{\boldsymbol\Sigma}\right|^{1/2}
     *           \left[1 +
     *                 \frac{1}{\nu}
     *                 ({\mathbf x}-{\boldsymbol\mu})^T
     *                 {\boldsymbol\Sigma}^{-1}
     *                 ({\mathbf x}-{\boldsymbol\mu})\right]^{(\nu+p)/2}} \f$
     *
     * at location \f${\mathbf x}\f$
     *
     *
     * \param variate sample which should be evaluated
     *
     * \throws See Gaussian<Variate>::has_full_rank()
     */
    Real log_probability(const Variate& x) const override
    {
        return cached_log_pdf_.log_probability(*this, x);
    }

    /**
     * \return Gaussian dimension
     */
    virtual constexpr int dimension() const
    {
        return normal_.dimension();
    }

    /**
     * \return t-distribution location
     */
    const Variate& mean() const override
    {
        return location();
    }

    /**
     * \return t-distribution scaling matrix
     *
     * \throws See Gaussian<Variate>::covariance()
     */
    const SecondMoment& covariance() const override
    {
        return normal_.covariance();
    }

    /**
     * \return t-distribution location
     */
    virtual const Variate& location() const
    {
        return normal_.mean();
    }

    /**
     * \return t-distribution degree-of-freedom
     */
    virtual Real degrees_of_freedom() const
    {
        return chi2_.degrees_of_freedom();
    }

    /**
     * Changes the dimension of the dynamic-size t-distribution and sets it to a
     * standard distribution with zero mean and identity covariance.
     *
     * \param new_dimension New dimension of the t-distribution
     *
     * \throws ResizingFixedSizeEntityException
     *         see standard_variate_dimension(int)
     */
    virtual void dimension(int new_dimension)
    {
        StdGaussianMappingBase::standard_variate_dimension(new_dimension + 1);
        normal_.dimension(new_dimension);
        cached_log_pdf_.flag_dirty();
    }

    /**
     * Sets the distribution location
     *
     * \param location New t-distribution mean
     *
     * \throws WrongSizeException
     */
    virtual void location(const Variate& new_location) noexcept
    {
        normal_.mean(new_location);
        cached_log_pdf_.flag_dirty();
    }

    /**
     * Sets the covariance matrix
     * \param covariance New covariance matrix
     *
     * \throws WrongSizeException
     */

    virtual void scaling_matrix(const SecondMoment& scaling_matrix)
    {
        normal_.covariance(scaling_matrix);
        cached_log_pdf_.flag_dirty();
    }

    /**
     * Sets t-distribution degree-of-freedom
     */
    virtual void degrees_of_freedom(Real dof)
    {
        chi2_.degrees_of_freedom(dof);
        cached_log_pdf_.flag_dirty();
    }

protected:
    /** \cond internal */
    ChiSquared chi2_;
    Gaussian<Variate> normal_;
    /** \endcond */

private:
    class CachedLogPdf
    {
    public:
        CachedLogPdf()
            : dirty_(true)
        { }

        /**
         * Evaluates the t-distribution pdf at a given position \c x
         */
        Real log_probability(
                const TDistribution<Variate>& t_distr, const Variate& x)
        {
            if (dirty_) update(t_distr);

            Variate z = x - t_distr.location();
            Real dof = t_distr.degrees_of_freedom();

            Real quad_term = (z.transpose() * t_distr.normal_.precision() * z);
            Real ln_term = std::log(Real(1) + quad_term  / dof);

            return const_term_ - const_factor_ * ln_term;
        }

        void flag_dirty() { dirty_ = true; }

    private:
        void update(const TDistribution<Variate>& t_distr)
        {
            Real half = Real(1)/Real(2);
            Real dim = t_distr.dimension();
            Real dof = t_distr.degrees_of_freedom();
            const_term_ =
                boost::math::lgamma(half * (dof + dim))
                - boost::math::lgamma(half * dof)
                - half * (dim * std::log(M_PI * dof))
                - half * (std::log(t_distr.normal_.covariance_determinant()));

            const_factor_ = half * (dof + dim);

            dirty_ = false;
        }

        bool dirty_;
        Real const_factor_;
        Real const_term_;
    };

    friend class CachedLogPdf;

    mutable CachedLogPdf cached_log_pdf_;
};

}

#endif
<|endoftext|>


<commit_before>#ifndef KGR_KANGARU_INCLUDE_KANGARU_DETAIL_AUTOWIRE_TRAITS_HPP
#define KGR_KANGARU_INCLUDE_KANGARU_DETAIL_AUTOWIRE_TRAITS_HPP

#include "traits.hpp"
#include "container_service.hpp"
#include "service_map.hpp"
#include "injected.hpp"

#include "../container.hpp"

namespace kgr {

template<typename, typename>
struct service;

namespace detail {
/*
 * This class is an object convertible to any mapped service.
 * Upon conversion, it calls the container to get that service.
 *
 * Primarely used for autowire services in constructors.
 */
template<typename For, typename Map>
struct deducer {
	explicit deducer(container& c) noexcept : _container{&c} {}

	template<typename T, enable_if_t<
		!std::is_base_of<For, mapped_service_t<T, Map>>::value &&
		!std::is_base_of<mapped_service_t<T, Map>, For>::value &&
		!std::is_reference<service_type<mapped_service_t<T, Map>>>::value, int> = 0>
	operator T () {
		return _container->service<mapped_service_t<T, Map>>();
	}

	template<typename T, enable_if_t<
		!std::is_base_of<For, mapped_service_t<T&, Map>>::value &&
		!std::is_base_of<mapped_service_t<T&, Map>, For>::value &&
		std::is_lvalue_reference<service_type<mapped_service_t<T&, Map>>>::value, int> = 0>
	operator T& () const {
		return _container->service<mapped_service_t<T&, Map>>();
	}

	template<typename T, enable_if_t<
		!std::is_base_of<For, mapped_service_t<T&&, Map>>::value &&
		!std::is_base_of<mapped_service_t<T&&, Map>, For>::value &&
		std::is_rvalue_reference<service_type<mapped_service_t<T&&, Map>>>::value, int> = 0>
	operator T&& () const {
		return _container->service<mapped_service_t<T&&, Map>>();
	}

private:
	container* _container;
};

/*
 * Alias that simply add a std::size_t parameter so it can be expanded using a sequence.
 */
template<typename For, typename Map, std::size_t>
using deducer_expand_t = deducer<For, Map>;

/*
 * Trait that check if a service is constructible using `n` amount of deducers.
 */
template<typename, typename, typename, std::size_t n, typename, typename = typename seq_gen<n>::type, typename = void>
struct is_deductible_from_amount_helper : std::false_type {};

/*
 * Specialization of amount_of_deductible_service_helper that exists when a callable constructor is found.
 * It also returns the injected result of the construct function (assuming a basic construct function)
 */
template<typename Service, typename T, typename Map, typename... Args, std::size_t... S, std::size_t n>
struct is_deductible_from_amount_helper<Service, T, Map, n, meta_list<Args...>, seq<S...>, enable_if_t<is_someway_constructible<T, deducer_expand_t<Service, Map, S>..., Args...>::value>> : std::true_type {
	using default_result_t = inject_result<deducer_expand_t<Service, Map, S>..., Args...>;
};

/*
 * Trait that tries to find the amount of deducer required.
 * Iterate from 0 to max deducers
 */
template<typename, typename, typename, typename, std::size_t, typename = void>
struct amount_of_deductible_service_helper {
	static constexpr bool deductible = false;
	static constexpr seq<> amount = {};
	using default_result_t = inject_result<>;
};

/*
 * Specialization of amount_of_deductible_service used when the service is constructible using the amount `n`
 */
template<typename S, typename T, typename Map, typename... Args, std::size_t n>
struct amount_of_deductible_service_helper<S, T, Map, meta_list<Args...>, n, enable_if_t<is_deductible_from_amount_helper<S, T, Map, n, meta_list<Args...>>::value>> {
	static constexpr bool deductible = true;
	static constexpr typename seq_gen<n>::type amount = {};
	using default_result_t = typename is_deductible_from_amount_helper<S, T, Map, n, meta_list<Args...>>::default_result_t;
};

/*
 * Specialization of amount_of_deductible_service_helper used when the service is not constructible with `n` deducer
 * Tries the next iteration.
 */
template<typename S, typename T, typename Map, typename... Args, std::size_t n>
struct amount_of_deductible_service_helper<S, T, Map, meta_list<Args...>, n, enable_if_t<!is_deductible_from_amount_helper<S, T, Map, n, meta_list<Args...>>::value && (n != 0)>> :
	amount_of_deductible_service_helper<S, T, Map, meta_list<Args...>, n - 1> {};

/*
 * The default maximum amount of deducer sent to the construct function when autowiring.
 * Tells how many autowired dependencies a service can have by default.
 */
constexpr std::size_t default_max_dependency = 8;

/*
 * Alias to amount_of_deductible_service_helper to ease usage
 */
template<typename S, typename T, typename Map, std::size_t max, typename... Args>
using amount_of_deductible_service = detail::amount_of_deductible_service_helper<S, T, Map, detail::meta_list<Args...>, max>;

/*
 * A class used for indirect mapping and tranmitting information about autowiring.
 */
template<template<typename, typename> class, template<typename> class, typename, std::size_t>
struct autowire_map;

template<template<typename, typename> class service_type, template<typename> class get_service, typename... Maps, std::size_t max_dependencies>
struct autowire_map<service_type, get_service, kgr::map<Maps...>, max_dependencies> {
	template<typename T>
	using mapped_service = service_type<detected_t<get_service, T>, autowire_map<service, decay_t, kgr::map<Maps...>, max_dependencies>>;
};

/*
 * The default injection function. Will call kgr::inject with all arguments.
 */
struct default_inject_function_t {
	template<typename... Args>
	constexpr auto operator()(Args&&... args) const -> inject_result<Args...> {
		return inject(std::forward<Args>(args)...);
	}
}
constexpr default_inject_function{};

/*
 * A construct function usable by many service definition implementation.
 * Will send as many deducers as there are numbers in S
 */
template<typename Self, typename Map, typename I, std::size_t... S, typename... Args>
inline auto deduce_construct(detail::seq<S...>, I inject, inject_t<container_service> cont, Args&&... args) -> detail::call_result_t<I, detail::deducer_expand_t<Self, Map, S>..., Args...> {
	auto& container = cont.forward();

	// The expansion of the inject call may be empty. This will silence the warning.
	static_cast<void>(container);

	return inject((void(S), detail::deducer<Self, Map>{container})..., std::forward<Args>(args)...);
}

/*
 * A shortcut for deduce_construct with the default injection function.
 */
template<typename Self, typename Map, std::size_t... S, typename... Args>
inline auto deduce_construct_default(detail::seq<S...> s, inject_t<container_service> cont, Args&&... args) -> detail::call_result_t<default_inject_function_t, detail::deducer_expand_t<Self, Map, S>..., Args...> {
	return deduce_construct<Self, Map>(s, default_inject_function, std::move(cont), std::forward<Args>(args)...);
}

/*
 * Tag that replaces dependencies in a service defintion. Carries all information on how to autowire.
 */
template<typename Map = map<>, std::size_t max_dependencies = detail::default_max_dependency>
using autowire_tag = detail::autowire_map<service, decay_t, Map, max_dependencies>;

} // namespace detail
} // namespace sbg

#endif
<commit_msg>Fix error detection and cycle detection with autowire<commit_after>#ifndef KGR_KANGARU_INCLUDE_KANGARU_DETAIL_AUTOWIRE_TRAITS_HPP
#define KGR_KANGARU_INCLUDE_KANGARU_DETAIL_AUTOWIRE_TRAITS_HPP

#include "traits.hpp"
#include "container_service.hpp"
#include "service_map.hpp"
#include "injected.hpp"

#include "../container.hpp"

namespace kgr {

template<typename, typename>
struct service;

namespace detail {

template<typename Service1, typename Service2>
using is_different_service = bool_constant<
	!std::is_base_of<Service1, Service2>::value &&
	!std::is_base_of<Service2, Service1>::value
>;

/*
 * This class is an object convertible to any mapped service.
 * Upon conversion, it calls the container to get that service.
 *
 * Primarely used for autowire services in constructors.
 */
template<typename For, typename Map>
struct deducer {
	explicit deducer(container& c) noexcept : _container{&c} {}

	template<typename T, enable_if_t<
		is_different_service<For, mapped_service_t<T, Map>>::value &&
		is_service_valid<mapped_service_t<T, Map>>::value &&
		!std::is_reference<service_type<mapped_service_t<T, Map>>>::value, int> = 0>
	operator T () {
		return _container->service<mapped_service_t<T, Map>>();
	}

	template<typename T, enable_if_t<
		is_different_service<For, mapped_service_t<T&, Map>>::value &&
		is_service_valid<mapped_service_t<T&, Map>>::value &&
		std::is_lvalue_reference<service_type<mapped_service_t<T&, Map>>>::value, int> = 0>
	operator T& () const {
		return _container->service<mapped_service_t<T&, Map>>();
	}

	template<typename T, enable_if_t<
		is_different_service<For, mapped_service_t<T&&, Map>>::value &&
		is_service_valid<mapped_service_t<T&&, Map>>::value &&
		std::is_rvalue_reference<service_type<mapped_service_t<T&&, Map>>>::value, int> = 0>
	operator T&& () const {
		return _container->service<mapped_service_t<T&&, Map>>();
	}

private:
	container* _container;
};

template<typename For, typename Map>
struct weak_deducer {
	template<typename T, enable_if_t<
		is_different_service<For, mapped_service_t<T, Map>>::value &&
		!std::is_reference<service_type<mapped_service_t<T, Map>>>::value, int> = 0>
	operator T ();

	template<typename T, enable_if_t<
		is_different_service<For, mapped_service_t<T&, Map>>::value &&
		std::is_lvalue_reference<service_type<mapped_service_t<T&, Map>>>::value, int> = 0>
	operator T& () const;

	template<typename T, enable_if_t<
		is_different_service<For, mapped_service_t<T&&, Map>>::value &&
		std::is_rvalue_reference<service_type<mapped_service_t<T&&, Map>>>::value, int> = 0>
	operator T&& () const;
};

/*
 * Alias that simply add a std::size_t parameter so it can be expanded using a sequence.
 */
template<typename For, typename Map, std::size_t>
using deducer_expand_t = deducer<For, Map>;

/*
 * Alias that simply add a std::size_t parameter so it can be expanded using a sequence.
 */
template<typename For, typename Map, std::size_t>
using weak_deducer_expand_t = weak_deducer<For, Map>;

/*
 * Trait that check if a service is constructible using `n` amount of deducers.
 */
template<typename, typename, typename, std::size_t n, typename, typename = typename seq_gen<n>::type, typename = void>
struct is_deductible_from_amount_helper : std::false_type {};

/*
 * Specialization of amount_of_deductible_service_helper that exists when a callable constructor is found.
 * It also returns the injected result of the construct function (assuming a basic construct function)
 */
template<typename Service, typename T, typename Map, typename... Args, std::size_t... S, std::size_t n>
struct is_deductible_from_amount_helper<Service, T, Map, n, meta_list<Args...>, seq<S...>, enable_if_t<is_someway_constructible<T, weak_deducer_expand_t<Service, Map, S>..., Args...>::value>> : std::true_type {
	using default_result_t = inject_result<deducer_expand_t<Service, Map, S>..., Args...>;
};

/*
 * Trait that tries to find the amount of deducer required.
 * Iterate from 0 to max deducers
 */
template<typename, typename, typename, typename, std::size_t, typename = void>
struct amount_of_deductible_service_helper {
	static constexpr bool deductible = false;
	static constexpr seq<> amount = {};
	using default_result_t = inject_result<>;
};

/*
 * Specialization of amount_of_deductible_service used when the service is constructible using the amount `n`
 */
template<typename S, typename T, typename Map, typename... Args, std::size_t n>
struct amount_of_deductible_service_helper<S, T, Map, meta_list<Args...>, n, enable_if_t<is_deductible_from_amount_helper<S, T, Map, n, meta_list<Args...>>::value>> {
	static constexpr bool deductible = true;
	static constexpr typename seq_gen<n>::type amount = {};
	using default_result_t = typename is_deductible_from_amount_helper<S, T, Map, n, meta_list<Args...>>::default_result_t;
};

/*
 * Specialization of amount_of_deductible_service_helper used when the service is not constructible with `n` deducer
 * Tries the next iteration.
 */
template<typename S, typename T, typename Map, typename... Args, std::size_t n>
struct amount_of_deductible_service_helper<S, T, Map, meta_list<Args...>, n, enable_if_t<!is_deductible_from_amount_helper<S, T, Map, n, meta_list<Args...>>::value && (n != 0)>> :
	amount_of_deductible_service_helper<S, T, Map, meta_list<Args...>, n - 1> {};

/*
 * The default maximum amount of deducer sent to the construct function when autowiring.
 * Tells how many autowired dependencies a service can have by default.
 */
constexpr std::size_t default_max_dependency = 8;

/*
 * Alias to amount_of_deductible_service_helper to ease usage
 */
template<typename S, typename T, typename Map, std::size_t max, typename... Args>
using amount_of_deductible_service = detail::amount_of_deductible_service_helper<S, T, Map, detail::meta_list<Args...>, max>;

/*
 * A class used for indirect mapping and tranmitting information about autowiring.
 */
template<template<typename, typename> class, template<typename> class, typename, std::size_t>
struct autowire_map;

template<template<typename, typename> class service_type, template<typename> class get_service, typename... Maps, std::size_t max_dependencies>
struct autowire_map<service_type, get_service, kgr::map<Maps...>, max_dependencies> {
	template<typename T>
	using mapped_service = service_type<detected_t<get_service, T>, autowire_map<service, decay_t, kgr::map<Maps...>, max_dependencies>>;
};

/*
 * The default injection function. Will call kgr::inject with all arguments.
 */
struct default_inject_function_t {
	template<typename... Args>
	constexpr auto operator()(Args&&... args) const -> inject_result<Args...> {
		return inject(std::forward<Args>(args)...);
	}
}
constexpr default_inject_function{};

/*
 * A construct function usable by many service definition implementation.
 * Will send as many deducers as there are numbers in S
 */
template<typename Self, typename Map, typename I, std::size_t... S, typename... Args>
inline auto deduce_construct(detail::seq<S...>, I inject, inject_t<container_service> cont, Args&&... args) -> detail::call_result_t<I, detail::deducer_expand_t<Self, Map, S>..., Args...> {
	auto& container = cont.forward();

	// The expansion of the inject call may be empty. This will silence the warning.
	static_cast<void>(container);

	return inject((void(S), detail::deducer<Self, Map>{container})..., std::forward<Args>(args)...);
}

/*
 * A shortcut for deduce_construct with the default injection function.
 */
template<typename Self, typename Map, std::size_t... S, typename... Args>
inline auto deduce_construct_default(detail::seq<S...> s, inject_t<container_service> cont, Args&&... args) -> detail::call_result_t<default_inject_function_t, detail::deducer_expand_t<Self, Map, S>..., Args...> {
	return deduce_construct<Self, Map>(s, default_inject_function, std::move(cont), std::forward<Args>(args)...);
}

/*
 * Tag that replaces dependencies in a service defintion. Carries all information on how to autowire.
 */
template<typename Map = map<>, std::size_t max_dependencies = detail::default_max_dependency>
using autowire_tag = detail::autowire_map<service, decay_t, Map, max_dependencies>;

} // namespace detail
} // namespace sbg

#endif
<|endoftext|>


<commit_before>#ifndef KGR_KANGARU_INCLUDE_KANGARU_DETAIL_OVERRIDE_TRAITS_HPP
#define KGR_KANGARU_INCLUDE_KANGARU_DETAIL_OVERRIDE_TRAITS_HPP

#include "traits.hpp"
#include "meta_list.hpp"
#include "detection.hpp"

namespace kgr {
namespace detail {

/*
 * Trait that check if all types specified in overrides are services
 */
template<typename T>
using is_override_services = all_of_traits<parent_types<T>, is_service>;

/*
 * Trait that check if the service type returned by
 * one override's service definitions can be converted to the service type of the service T definition.
 */
template<typename Parent, typename T>
using is_one_override_convertible = is_explicitly_convertible<service_type<T>, detected_t<service_type, Parent>>;

/*
 * Trait that check if the service type returned by
 * all overriden service definitions can be converted to the service type of the service T definition.
 */
template<typename T>
using is_override_convertible = all_of_traits<parent_types<T>, is_one_override_convertible, T>;

/*
 * Trait that check if all overriden services are polymorphic
 */
template<typename T>
using is_override_polymorphic = all_of_traits<parent_types<T>, is_polymorphic>;

/*
 * Trait that check if no overriden services are final
 */
template<typename T>
using is_override_not_final = all_of_traits<parent_types<T>, is_not_final_service>;

/*
 * Trait that check if the default service of an abstract service overrides that abstract service
 */
template<typename T>
using is_default_overrides_abstract = bool_constant<
	!has_default<T>::value || is_overriden_by<T, detected_t<default_type, T>>::value
>;

/*
 * Trait that check if the default service type is convertible to the abstract service type.
 */
template<typename T>
using is_default_convertible = bool_constant<
	!has_default<T>::value || is_explicitly_convertible<
		detected_t<service_type, detected_t<default_type, T>>,
		detected_t<service_type, T>
	>::value
>;

} // namespace detail
} // namespace kgr

#endif // KGR_KANGARU_INCLUDE_KANGARU_DETAIL_OVERRIDE_TRAITS_HPP
<commit_msg>Make the new override traits work under visual studio 2015<commit_after>#ifndef KGR_KANGARU_INCLUDE_KANGARU_DETAIL_OVERRIDE_TRAITS_HPP
#define KGR_KANGARU_INCLUDE_KANGARU_DETAIL_OVERRIDE_TRAITS_HPP

#include "traits.hpp"
#include "meta_list.hpp"
#include "detection.hpp"

namespace kgr {
namespace detail {

/*
 * Trait that check if all types specified in overrides are services
 */
template<typename T>
using is_override_services = all_of_traits<parent_types<T>, is_service>;

/*
 * Trait that check if the service type returned by
 * one override's service definitions can be converted to the service type of the service T definition.
 */
template<typename Parent, typename T>
using is_one_override_convertible = is_explicitly_convertible<detected_t<service_type, T>, detected_t<service_type, Parent>>;

/*
 * Trait that check if the service type returned by
 * all overriden service definitions can be converted to the service type of the service T definition.
 */
template<typename T>
using is_override_convertible = all_of_traits<parent_types<T>, is_one_override_convertible, T>;

/*
 * Trait that check if all overriden services are polymorphic
 */
template<typename T>
using is_override_polymorphic = all_of_traits<parent_types<T>, is_polymorphic>;

/*
 * Trait that check if no overriden services are final
 */
template<typename T>
using is_override_not_final = all_of_traits<parent_types<T>, is_not_final_service>;

/*
 * Trait that check if the default service of an abstract service overrides that abstract service
 */
template<typename T>
using is_default_overrides_abstract = bool_constant<
	!has_default<T>::value || is_overriden_by<T, detected_t<default_type, T>>::value
>;

/*
 * Trait that check if the default service type is convertible to the abstract service type.
 */
template<typename T>
using is_default_convertible = bool_constant<
	!has_default<T>::value || is_explicitly_convertible<
		detected_t<service_type, detected_t<default_type, T>>,
		detected_t<service_type, T>
	>::value
>;

} // namespace detail
} // namespace kgr

#endif // KGR_KANGARU_INCLUDE_KANGARU_DETAIL_OVERRIDE_TRAITS_HPP
<|endoftext|>


<commit_before>// Copyright 2010-2013 RethinkDB, all rights reserved.

#include <map>
#include <stdexcept>
#include <string>
#include <vector>

namespace options {

struct parse_error_t : public std::runtime_error {
    parse_error_t(const std::string &msg) : std::runtime_error(msg) { }
};

struct validation_error_t : public std::runtime_error {
    validation_error_t(const std::string &msg) : std::runtime_error(msg) { }
};

struct file_parse_error_t : public std::runtime_error {
    file_parse_error_t(const std::string &msg) : std::runtime_error(msg) { }
};

// Represents an option's names.  Be sure to include dashes!  Usage:
//
//     names_t("--max-foobars")  // An option name.
//     names_t("--cores", "-c")  // An option name with an abbreviation
class names_t {
public:
    // Include dashes.  For example, name might be "--blah".
    explicit names_t(std::string name) {
        names.push_back(name);
    }
    // Include the right amount of dashes.  For example, official_name might
    // be "--help", and other_name might be "-h".
    names_t(std::string official_name, std::string other_name) {
        names.push_back(official_name);
        names.push_back(other_name);
    }
private:
    friend class option_t;
    std::vector<std::string> names;
};

// Pass one of these to the option_t construct to tell what kind of argument you have.
enum appearance_t {
    // A mandatory argument that can be passed once.
    MANDATORY,
    // A mandatory argument that may be repeated.
    MANDATORY_REPEAT,
    // An optional argument, that may be passed zero or one times.
    OPTIONAL,
    // An optional argument, that may be repeated.
    OPTIONAL_REPEAT,
    // An optional argument that doesn't take a parameter.  Useful for "--help".
    OPTIONAL_NO_PARAMETER
};

// A command line option with a name, specification of how many times it may appear, and whether it
// takes a parameter.
//
// Examples:
//     // An option that may be used at most once, with no parameter.
//     option_t(names_t("--help", "-h"), OPTIONAL_NO_PARAMETER)
//     // An option that may be used at most once, with a default value.  The user
//     // could pass --cores 3 or -c 3, but not a naked -c.
//     option_t(names_t("--cores", "-c"), OPTIONAL, strprintf("%d", get_cpu_count()));
//     // An option that must appear one or more times.
//     option_t(names_t("--join", "-j"), MANDATORY_REPEAT)
class option_t {
public:
    // Creates an option with the appropriate name and appearance specifier,
    // with a default value being the empty vector.
    explicit option_t(names_t names, appearance_t appearance);
    // Creates an option with the appropriate name and appearance specifier,
    // with the default value being a vector of size 1.  OPTIONAL and
    // OPTIONAL_REPEAT are the only valid appearance specifiers.
    explicit option_t(names_t names, appearance_t appearance, std::string default_value);

private:
    friend std::map<std::string, std::vector<std::string> > default_values_map(const std::vector<option_t> &options);
    friend std::map<std::string, std::vector<std::string> > do_parse_command_line(
        const int argc, const char *const *const argv, const std::vector<option_t> &options,
        std::vector<std::string> *const unrecognized_out);
    friend const option_t *find_option(const char *const option_name, const std::vector<option_t> &options);
    friend void verify_option_counts(const std::vector<option_t> &options,
                                     const std::map<std::string, std::vector<std::string> > &names_by_values);
    // Names for the option, e.g. "-j", "--join"
    std::vector<std::string> names;

    // How many times must the option appear?  If an option appears zero times,
    // and if min_appearances is zero, then `default_values` will be used as the
    // value-list of the option.  Typical combinations of (min_appearances,
    // max_appearances) are (0, 1) (with a default_value), (0, SIZE_MAX) (with or
    // without a default value), (1, 1) (for mandatory options), (1, SIZE_MAX)
    // (for mandatory options with repetition).
    //
    // It must be the case that 0 <= min_appearances <= max_appearances <=
    // SIZE_MAX.
    size_t min_appearances;
    size_t max_appearances;

    // True if an option doesn't take a parameter.  For example, "--help" would
    // take no parameter.
    bool no_parameter;

    // The value(s) to use if no appearances of the command line option are
    // available.  This is only relevant if min_appearances == 0.
    std::vector<std::string> default_values;
};

// Parses options from a command line into a return value.  Uses empty-string parameter values for
// appearances of OPTIONAL_NO_PARAMETER options.  Uses the *official name* of the option (the first
// parameter passed to names_t) for map keys.  Does not do any verification that we have the right
// number of option values.  (That only happens in `verify_option_counts`.)
std::map<std::string, std::vector<std::string> > parse_command_line(int argc, const char *const *argv, const std::vector<option_t> &options);

// Like `parse_command_line`, except that it tolerates unrecognized options, instead of throwing.
// Out-of-place positional parameters and unrecognized options are output to `*unrecognized_out`, in
// the same order that they appeared in the options list.  This can lead to some weird situations,
// if you passed "--recognized-foo 3 --unrecognized --recognized-bar 4 5" on the command line.  You
// would get ["--unrecognized", "5"] in `*unrecognized_out`.
std::map<std::string, std::vector<std::string> > parse_command_line_and_collect_unrecognized(
    int argc, const char *const *argv, const std::vector<option_t> &options,
    std::vector<std::string> *unrecognized_out);

// Merges option values from two different sources together, with higher precedence going to the
// left-hand argument.  Example usage:
//
//     opts = merge(command_line_values, config_file_values);
std::map<std::string, std::vector<std::string> > merge(
    const std::map<std::string, std::vector<std::string> > &high_precedence_values,
    const std::map<std::string, std::vector<std::string> > &low_precedence_values);

// Verifies that given options build the right amount of times.  This is separate from option
// parsing because we need to accumulate options from both the command line and config file.
void verify_option_counts(const std::vector<option_t> &options,
                          const std::map<std::string, std::vector<std::string> > &names_by_values);

// Constructs a map of default option values.
std::map<std::string, std::vector<std::string> > default_values_map(const std::vector<option_t> &options);

// Parses the file contents, using filepath solely to help build error messages, retrieving some
// options.
std::map<std::string, std::vector<std::string> > parse_config_file(const std::string &contents,
                                                                   const std::string &filepath,
                                                                   const std::vector<option_t> &options);

struct help_line_t {
    help_line_t(const std::string &_syntax_description,
                const std::string &_blurb)
        : syntax_description(_syntax_description), blurb(_blurb) { }

    std::string syntax_description;
    std::string blurb;
};

struct help_section_t {
    help_section_t() { }
    help_section_t(const std::string &_section_name)
        : section_name(_section_name) { }
    help_section_t(const std::string &_section_name, const std::vector<help_line_t> &_help_lines)
        : section_name(_section_name), help_lines(_help_lines) { }

    void add(const std::string &syntax_description, const std::string &blurb) {
        help_lines.push_back(help_line_t(syntax_description, blurb));
    }

    std::string section_name;
    std::vector<help_line_t> help_lines;
};

std::string format_help(const std::vector<help_section_t> &help);

}  // namespace options

<commit_msg>Added some const reference parameters and comment strings.<commit_after>// Copyright 2010-2013 RethinkDB, all rights reserved.

#include <map>
#include <stdexcept>
#include <string>
#include <vector>

namespace options {

struct parse_error_t : public std::runtime_error {
    parse_error_t(const std::string &msg) : std::runtime_error(msg) { }
};

struct validation_error_t : public std::runtime_error {
    validation_error_t(const std::string &msg) : std::runtime_error(msg) { }
};

struct file_parse_error_t : public std::runtime_error {
    file_parse_error_t(const std::string &msg) : std::runtime_error(msg) { }
};

// Represents an option's names.  Be sure to include dashes!  Usage:
//
//     names_t("--max-foobars")  // An option name.
//     names_t("--cores", "-c")  // An option name with an abbreviation
class names_t {
public:
    // Include dashes.  For example, name might be "--blah".
    explicit names_t(const std::string &name) {
        names.push_back(name);
    }
    // Include the right amount of dashes.  For example, official_name might
    // be "--help", and other_name might be "-h".
    names_t(std::string official_name, std::string other_name) {
        names.push_back(official_name);
        names.push_back(other_name);
    }
private:
    friend class option_t;
    std::vector<std::string> names;
};

// Pass one of these to the option_t construct to tell what kind of argument you have.
enum appearance_t {
    // A mandatory argument that can be passed once.
    MANDATORY,
    // A mandatory argument that may be repeated.
    MANDATORY_REPEAT,
    // An optional argument, that may be passed zero or one times.
    OPTIONAL,
    // An optional argument, that may be repeated.
    OPTIONAL_REPEAT,
    // An optional argument that doesn't take a parameter.  Useful for "--help".
    OPTIONAL_NO_PARAMETER
};

// A command line option with a name, specification of how many times it may appear, and whether it
// takes a parameter.
//
// Examples:
//     // An option that may be used at most once, with no parameter.
//     option_t(names_t("--help", "-h"), OPTIONAL_NO_PARAMETER)
//     // An option that may be used at most once, with a default value.  The user
//     // could pass --cores 3 or -c 3, but not a naked -c.
//     option_t(names_t("--cores", "-c"), OPTIONAL, strprintf("%d", get_cpu_count()));
//     // An option that must appear one or more times.
//     option_t(names_t("--join", "-j"), MANDATORY_REPEAT)
class option_t {
public:
    // Creates an option with the appropriate name and appearance specifier,
    // with a default value being the empty vector.
    explicit option_t(names_t names, appearance_t appearance);
    // Creates an option with the appropriate name and appearance specifier,
    // with the default value being a vector of size 1.  OPTIONAL and
    // OPTIONAL_REPEAT are the only valid appearance specifiers.
    explicit option_t(names_t names, appearance_t appearance, std::string default_value);

private:
    friend std::map<std::string, std::vector<std::string> > default_values_map(const std::vector<option_t> &options);
    friend std::map<std::string, std::vector<std::string> > do_parse_command_line(
        const int argc, const char *const *const argv, const std::vector<option_t> &options,
        std::vector<std::string> *const unrecognized_out);
    friend const option_t *find_option(const char *const option_name, const std::vector<option_t> &options);
    friend void verify_option_counts(const std::vector<option_t> &options,
                                     const std::map<std::string, std::vector<std::string> > &names_by_values);
    // Names for the option, e.g. "-j", "--join"
    std::vector<std::string> names;

    // How many times must the option appear?  If an option appears zero times,
    // and if min_appearances is zero, then `default_values` will be used as the
    // value-list of the option.  Typical combinations of (min_appearances,
    // max_appearances) are (0, 1) (with a default_value), (0, SIZE_MAX) (with or
    // without a default value), (1, 1) (for mandatory options), (1, SIZE_MAX)
    // (for mandatory options with repetition).
    //
    // It must be the case that 0 <= min_appearances <= max_appearances <=
    // SIZE_MAX.
    size_t min_appearances;
    size_t max_appearances;

    // True if an option doesn't take a parameter.  For example, "--help" would
    // take no parameter.
    bool no_parameter;

    // The value(s) to use if no appearances of the command line option are
    // available.  This is only relevant if min_appearances == 0.
    std::vector<std::string> default_values;
};

// Parses options from a command line into a return value.  Uses empty-string parameter values for
// appearances of OPTIONAL_NO_PARAMETER options.  Uses the *official name* of the option (the first
// parameter passed to names_t) for map keys.  Does not do any verification that we have the right
// number of option values.  (That only happens in `verify_option_counts`.)
std::map<std::string, std::vector<std::string> > parse_command_line(int argc, const char *const *argv, const std::vector<option_t> &options);

// Like `parse_command_line`, except that it tolerates unrecognized options, instead of throwing.
// Out-of-place positional parameters and unrecognized options are output to `*unrecognized_out`, in
// the same order that they appeared in the options list.  This can lead to some weird situations,
// if you passed "--recognized-foo 3 --unrecognized --recognized-bar 4 5" on the command line.  You
// would get ["--unrecognized", "5"] in `*unrecognized_out`.
std::map<std::string, std::vector<std::string> > parse_command_line_and_collect_unrecognized(
    int argc, const char *const *argv, const std::vector<option_t> &options,
    std::vector<std::string> *unrecognized_out);

// Merges option values from two different sources together, with higher precedence going to the
// left-hand argument.  Example usage:
//
//     opts = merge(command_line_values, config_file_values);
std::map<std::string, std::vector<std::string> > merge(
    const std::map<std::string, std::vector<std::string> > &high_precedence_values,
    const std::map<std::string, std::vector<std::string> > &low_precedence_values);

// Verifies that given options build the right amount of times.  This is separate from option
// parsing because we need to accumulate options from both the command line and config file.
void verify_option_counts(const std::vector<option_t> &options,
                          const std::map<std::string, std::vector<std::string> > &names_by_values);

// Constructs a map of default option values.
std::map<std::string, std::vector<std::string> > default_values_map(const std::vector<option_t> &options);

// Parses the file contents, using filepath solely to help build error messages, retrieving some
// options.
std::map<std::string, std::vector<std::string> > parse_config_file(const std::string &contents,
                                                                   const std::string &filepath,
                                                                   const std::vector<option_t> &options);

// A help_line_t is a syntax description and a blurb.  When used in a help_section_t, the blurbs get
// aligned and word-wrapped.
struct help_line_t {
    help_line_t(const std::string &_syntax_description,
                const std::string &_blurb)
        : syntax_description(_syntax_description), blurb(_blurb) { }

    std::string syntax_description;
    std::string blurb;
};

// A help_section_t is a titled list of syntax descriptions and blurbs.  When rendered with
// format_help, all the blurbs get aligned and word-wrapped.
struct help_section_t {
    help_section_t() { }
    help_section_t(const std::string &_section_name)
        : section_name(_section_name) { }
    help_section_t(const std::string &_section_name, const std::vector<help_line_t> &_help_lines)
        : section_name(_section_name), help_lines(_help_lines) { }

    void add(const std::string &syntax_description, const std::string &blurb) {
        help_lines.push_back(help_line_t(syntax_description, blurb));
    }

    std::string section_name;
    std::vector<help_line_t> help_lines;
};

// Creates a help string suitable for output from --help, aligning and word-wrapping the blurbs.
std::string format_help(const std::vector<help_section_t> &help);

}  // namespace options

<|endoftext|>