<commit_before>/*
 * Oracle Berkeley DB XML-based treebank reader.
 * Written by Lars Buitinck.
 *
 * The basic format is explained in the header. An additional notes:
 *  - We use DBML_WELL_FORMED_ONLY to prevent having to read the DTD.
 *    This only works because the DTD does not define entities.
 */

#include <AlpinoCorpus/CorpusReader.hh>
#include <AlpinoCorpus/DbCorpusReader.hh>
#include <AlpinoCorpus/Error.hh>

#include <QScopedPointer>
#include <QString>
#include <sstream>
#include <stdexcept>
#include <string>
#include <typeinfo>
#include <iostream>

#include <dbxml/DbXml.hpp>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/framework/MemBufInputSource.hpp>
#include <xercesc/framework/MemBufFormatTarget.hpp>
#include <xercesc/framework/Wrapper4InputSource.hpp>

#include <xqilla/xqilla-dom3.hpp>

namespace db = DbXml;

namespace xerces = XERCES_CPP_NAMESPACE;

namespace {
    QString toQString(std::string const &s)
    {
        return QString::fromUtf8(s.c_str());
    }
}

namespace alpinocorpus {

class DbCorpusReaderPrivate : public CorpusReader
{
    // XXX mutable is hideous, but saves a lot of const_casts: the read
    // methods are nominally const (don't change future behavior and are
    // thread-safe), but DB XML doesn't expose const reading methods.
    DbXml::XmlManager   mutable mgr;
    DbXml::XmlContainer mutable container;
    std::string collection;

    class DbIter : public CorpusReader::IterImpl
    {
    public:
        DbIter(DbXml::XmlContainer &);
        DbIter(DbXml::XmlManager &);

        QString current() const;
        bool equals(IterImpl const &) const;
        void next();

    protected:
        mutable DbXml::XmlResults r;

        DbIter(DbXml::XmlResults const &);
    };

    struct QueryIter : public DbIter
    {
        QueryIter(DbXml::XmlResults const &);
        QString contents(CorpusReader const &) const;
    };

public:
    DbCorpusReaderPrivate(QString const &);
    virtual ~DbCorpusReaderPrivate();
    EntryIterator getBegin() const;
    EntryIterator getEnd() const;
    size_t getSize() const
    {
        return const_cast<DbXml::XmlContainer &>(container).getNumDocuments();
    }
    bool validQuery(QueryDialect d, bool variables, QString const &query) const;
    QString readEntry(QString const &) const;
    QString readEntryMarkQuery(QString const &entry, QueryDialect d, QString const &query,
        QString const &attr, QString const &value) const;
    EntryIterator runXPath(QString const &) const;
    EntryIterator runXQuery(QString const &) const;

private:
    void setNameAndCollection(QString const &);

};

DbCorpusReader::DbCorpusReader(QString const &name) :
    d_private(new DbCorpusReaderPrivate(name))
{
}

DbCorpusReader::~DbCorpusReader()
{
}

/* begin() */
DbCorpusReaderPrivate::DbIter::DbIter(db::XmlContainer &container)
{
    try {
        r = container.getAllDocuments( db::DBXML_LAZY_DOCS
                                     | db::DBXML_WELL_FORMED_ONLY
                                     );
    } catch (db::XmlException const &e) {
        throw alpinocorpus::Error(e.what());
    }
}

/* query */
DbCorpusReaderPrivate::DbIter::DbIter(db::XmlResults const &r_)
 : r(r_)
{
}

/* end() */
DbCorpusReaderPrivate::DbIter::DbIter(db::XmlManager &mgr)
 : r(mgr.createResults())   // builds empty XmlResults
{
}

/* operator* */
QString DbCorpusReaderPrivate::DbIter::current() const
{
    db::XmlDocument doc;
    r.peek(doc);
    return toQString(doc.getName());
}

/* operator== */
bool DbCorpusReaderPrivate::DbIter::equals(IterImpl const &that) const
{
    try {
        // The const_casts are needed because hasNext() is not const.
        // XXX should be safe.
        DbIter &other= const_cast<DbIter&>(dynamic_cast<DbIter const &>(that));
        DbIter &self = const_cast<DbIter&>(*this);
        try {
            if (!self.r.hasNext() && !other.r.hasNext())
                return true;        // both at end()
        } catch (db::XmlException const &e) {
            throw alpinocorpus::Error(e.what());
        }
        return self.r == other.r;
    } catch (std::bad_cast const &e) {
        return false;
    }
}

/* operator++ */
void DbCorpusReaderPrivate::DbIter::next()
{
    try {
        db::XmlDocument doc;
        r.next(doc);
    } catch (db::XmlException const &e) {
        throw alpinocorpus::Error(e.what());
    }
}

DbCorpusReaderPrivate::QueryIter::QueryIter(db::XmlResults const &r)
 : DbIter(r)
{
}

QString DbCorpusReaderPrivate::QueryIter::contents(CorpusReader const &) const
{
    db::XmlValue v;
    r.peek(v);
    return toQString(v.getNodeValue());
}

CorpusReader::EntryIterator DbCorpusReader::getBegin() const
{
    return d_private->getBegin();
}

CorpusReader::EntryIterator DbCorpusReader::getEnd() const
{
    return d_private->getEnd();
}

size_t DbCorpusReader::getSize() const
{
    return d_private->getSize();
}

bool DbCorpusReader::validQuery(QueryDialect d, bool variables, QString const &query) const
{
    return d_private->isValidQuery(d, variables, query);
}

QString DbCorpusReader::readEntry(const QString &entry) const
{
    return d_private->readEntry(entry);
}

QString DbCorpusReader::readEntryMarkQuery(QString const &entry, QueryDialect d, QString const &query,
    QString const &attr, QString const &value) const
{
    return d_private->readEntryMarkQuery(entry, d, query, attr, value);
}

CorpusReader::EntryIterator DbCorpusReader::runXPath(QString const &query) const
{
    return d_private->runXPath(query);
}

CorpusReader::EntryIterator DbCorpusReader::runXQuery(QString const &query) const
{
    return d_private->runXQuery(query);
}

DbCorpusReaderPrivate::DbCorpusReaderPrivate(QString const &qpath)
 : mgr(), container()
{
    std::string path(qpath.toLocal8Bit().data());

    try {
        db::XmlContainerConfig config;
        config.setReadOnly(true);
        container = mgr.openContainer(path, config);
        // Nasty: using a hard-coded alias to work use in the xpath queries.
        container.addAlias("corpus");
        setNameAndCollection(qpath);
    } catch (db::XmlException const &e) {
        throw OpenError(qpath, QString::fromUtf8(e.what()));
    }
}

DbCorpusReaderPrivate::~DbCorpusReaderPrivate()
{
}

CorpusReader::EntryIterator DbCorpusReaderPrivate::getBegin() const
{
    return EntryIterator(new DbIter(container));
}

CorpusReader::EntryIterator DbCorpusReaderPrivate::getEnd() const
{
    return EntryIterator(new DbIter(mgr));
}

bool DbCorpusReaderPrivate::validQuery(QueryDialect d, bool variables, QString const &query) const
{
    try {
        db::XmlQueryContext ctx = mgr.createQueryContext();
        QByteArray queryData(query.toUtf8());
        mgr.prepare(queryData.constData(), ctx);
    } catch (db::XmlException const &e) {
        return false;
    }

    return true;
}

QString DbCorpusReaderPrivate::readEntry(QString const &filename) const
{
    std::string name(filename.toUtf8().data());

    try {
        db::XmlDocument doc(container.getDocument(name, db::DBXML_LAZY_DOCS));
        std::string content;
        return toQString(doc.getContent(content));

    } catch (db::XmlException const &e) {
        std::ostringstream msg;
        msg << "entry \""                  << name
            << "\" cannot be read from \"" << container.getName()
            << "\" ("                      << e.what()
            << ")";
        throw Error(msg.str());
    }
}

QString DbCorpusReaderPrivate::readEntryMarkQuery(QString const &entry, QueryDialect d, QString const &query,
    QString const &attr, QString const &value) const
{
    std::string name(entry.toUtf8().data());
    std::string content;
    QByteArray attrArray(attr.toUtf8());
    QByteArray valArray(value.toUtf8());

    try {
        db::XmlDocument doc(container.getDocument(name, db::DBXML_LAZY_DOCS));
        doc.getContent(content);
    } catch (db::XmlException const &e) {
        std::ostringstream msg;
        msg << "entry \""                  << name
        << "\" cannot be read from \"" << container.getName()
        << "\" ("                      << e.what()
        << ")";
        throw Error(msg.str());
    }

    QByteArray utf8Query(query.toUtf8());

    // Prepare the DOM parser.
    xerces::DOMImplementation *xqillaImplementation =
        xerces::DOMImplementationRegistry::getDOMImplementation(X("XPath2 3.0"));
    QScopedPointer<xerces::DOMLSParser> parser(xqillaImplementation->createLSParser(
        xerces::DOMImplementationLS::MODE_SYNCHRONOUS, 0));

    // Parse the document.
    xerces::MemBufInputSource xmlInput(reinterpret_cast<XMLByte const *>(content.c_str()),
        content.size(), "input");

    xerces::Wrapper4InputSource domInput(&xmlInput, false);

    xerces::DOMDocument *document;
    try {
        document = parser->parse(&domInput);
    } catch (xerces::DOMException const &e) {
        throw Error(std::string("Could not parse XML data: ") + UTF8(e.getMessage()));
    }

    QScopedPointer<xerces::DOMXPathExpression> expression;
    try {
        expression.reset(document->createExpression(X(utf8Query.constData()), 0));
    } catch (xerces::DOMXPathException const &) {
        throw Error("Could not parse expression.");
    } catch (xerces::DOMException const &) {
        throw Error("Could not resolve namespace prefixes.");
    }

    QScopedPointer<xerces::DOMXPathResult> result;
    try {
        result.reset(expression->evaluate(document,
            xerces::DOMXPathResult::ITERATOR_RESULT_TYPE, 0));
    } catch (xerces::DOMXPathException const &e) {
        throw Error("Could not retrieve an iterator over evaluation results.");
    } catch (xerces::DOMException &e) {
        throw Error("Could not evaluate the expression on the given document.");
    }

    QList<xerces::DOMNode *> markNodes;

    while (result->iterateNext())
    {
        xerces::DOMNode *node = result->getNodeValue();

        // Skip non-element nodes
        if (node->getNodeType() != xerces::DOMNode::ELEMENT_NODE)
            continue;

        markNodes.append(node);
    }

    for (QList<xerces::DOMNode *>::iterator iter = markNodes.begin();
         iter != markNodes.end(); ++iter)
    {
        xerces::DOMNode *node = *iter;

        xerces::DOMNamedNodeMap *map = node->getAttributes();
        if (map == 0)
            continue;

        // Create new attribute node.
        xerces::DOMAttr *attr;
        try {
            attr = document->createAttribute(X(attrArray.constData()));
        } catch (xerces::DOMException const &e) {
            throw Error("Attribute name contains invalid character.");
        }
        attr->setNodeValue(X(valArray.constData()));

        map->setNamedItem(attr);

    }

    // Serialize DOM tree
    QScopedPointer<xerces::DOMLSSerializer> serializer(xqillaImplementation->createLSSerializer());
    QScopedPointer<xerces::DOMLSOutput> output(xqillaImplementation->createLSOutput());
    xerces::MemBufFormatTarget target;
    output->setByteStream(&target);
    serializer->write(document, output.data());

    QByteArray outArray(reinterpret_cast<char const *>(target.getRawBuffer()),
        target.getLen());

    return QString::fromUtf8(outArray);
}

CorpusReader::EntryIterator DbCorpusReaderPrivate::runXPath(QString const &query) const
{
    return runXQuery(QString("collection('corpus')" + query));
}

CorpusReader::EntryIterator DbCorpusReaderPrivate::runXQuery(QString const &query)
    const
{
    // XXX use DBXML_DOCUMENT_PROJECTION and return to whole-doc containers?

    try {
        db::XmlQueryContext ctx
            = mgr.createQueryContext(db::XmlQueryContext::LiveValues,
                                     db::XmlQueryContext::Lazy);
        ctx.setDefaultCollection(collection);
        db::XmlResults r(mgr.query(query.toUtf8().data(), ctx,
                                     db::DBXML_LAZY_DOCS
                                   | db::DBXML_WELL_FORMED_ONLY
                                  ));
        return EntryIterator(new QueryIter(r));
    } catch (db::XmlException const &e) {
        throw alpinocorpus::Error(e.what());
    }
}

/*
 * Set corpus name to container name; set collection to a usable collection
 * name.
 *
 * The collection name is used for querying. We set it to the absolute path
 * so we can still run queries after a chdir().
 * For some reason, DB XML strips off a leading slash in the filename,
 * so we prepend an extra one.
 */
void DbCorpusReaderPrivate::setNameAndCollection(QString const &path)
{
    //collection = QFileInfo(path).absoluteFilePath().toLocal8Bit().data();

    setName(toQString(container.getName()));

    collection = std::string("/") + name().toLocal8Bit().data();
}

}   // namespace alpinocorpus
<commit_msg>Use AutoRelease for pointers to Xerces-C and XQilla objects.<commit_after>/*
 * Oracle Berkeley DB XML-based treebank reader.
 * Written by Lars Buitinck.
 *
 * The basic format is explained in the header. An additional notes:
 *  - We use DBML_WELL_FORMED_ONLY to prevent having to read the DTD.
 *    This only works because the DTD does not define entities.
 */

#include <AlpinoCorpus/CorpusReader.hh>
#include <AlpinoCorpus/DbCorpusReader.hh>
#include <AlpinoCorpus/Error.hh>

#include <QString>
#include <sstream>
#include <stdexcept>
#include <string>
#include <typeinfo>
#include <iostream>

#include <dbxml/DbXml.hpp>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/framework/MemBufInputSource.hpp>
#include <xercesc/framework/MemBufFormatTarget.hpp>
#include <xercesc/framework/Wrapper4InputSource.hpp>

#include <xqilla/xqilla-dom3.hpp>

namespace db = DbXml;

namespace xerces = XERCES_CPP_NAMESPACE;

namespace {
    QString toQString(std::string const &s)
    {
        return QString::fromUtf8(s.c_str());
    }
}

namespace alpinocorpus {

class DbCorpusReaderPrivate : public CorpusReader
{
    // XXX mutable is hideous, but saves a lot of const_casts: the read
    // methods are nominally const (don't change future behavior and are
    // thread-safe), but DB XML doesn't expose const reading methods.
    DbXml::XmlManager   mutable mgr;
    DbXml::XmlContainer mutable container;
    std::string collection;

    class DbIter : public CorpusReader::IterImpl
    {
    public:
        DbIter(DbXml::XmlContainer &);
        DbIter(DbXml::XmlManager &);

        QString current() const;
        bool equals(IterImpl const &) const;
        void next();

    protected:
        mutable DbXml::XmlResults r;

        DbIter(DbXml::XmlResults const &);
    };

    struct QueryIter : public DbIter
    {
        QueryIter(DbXml::XmlResults const &);
        QString contents(CorpusReader const &) const;
    };

public:
    DbCorpusReaderPrivate(QString const &);
    virtual ~DbCorpusReaderPrivate();
    EntryIterator getBegin() const;
    EntryIterator getEnd() const;
    size_t getSize() const
    {
        return const_cast<DbXml::XmlContainer &>(container).getNumDocuments();
    }
    bool validQuery(QueryDialect d, bool variables, QString const &query) const;
    QString readEntry(QString const &) const;
    QString readEntryMarkQuery(QString const &entry, QueryDialect d, QString const &query,
        QString const &attr, QString const &value) const;
    EntryIterator runXPath(QString const &) const;
    EntryIterator runXQuery(QString const &) const;

private:
    void setNameAndCollection(QString const &);

};

DbCorpusReader::DbCorpusReader(QString const &name) :
    d_private(new DbCorpusReaderPrivate(name))
{
}

DbCorpusReader::~DbCorpusReader()
{
}

/* begin() */
DbCorpusReaderPrivate::DbIter::DbIter(db::XmlContainer &container)
{
    try {
        r = container.getAllDocuments( db::DBXML_LAZY_DOCS
                                     | db::DBXML_WELL_FORMED_ONLY
                                     );
    } catch (db::XmlException const &e) {
        throw alpinocorpus::Error(e.what());
    }
}

/* query */
DbCorpusReaderPrivate::DbIter::DbIter(db::XmlResults const &r_)
 : r(r_)
{
}

/* end() */
DbCorpusReaderPrivate::DbIter::DbIter(db::XmlManager &mgr)
 : r(mgr.createResults())   // builds empty XmlResults
{
}

/* operator* */
QString DbCorpusReaderPrivate::DbIter::current() const
{
    db::XmlDocument doc;
    r.peek(doc);
    return toQString(doc.getName());
}

/* operator== */
bool DbCorpusReaderPrivate::DbIter::equals(IterImpl const &that) const
{
    try {
        // The const_casts are needed because hasNext() is not const.
        // XXX should be safe.
        DbIter &other= const_cast<DbIter&>(dynamic_cast<DbIter const &>(that));
        DbIter &self = const_cast<DbIter&>(*this);
        try {
            if (!self.r.hasNext() && !other.r.hasNext())
                return true;        // both at end()
        } catch (db::XmlException const &e) {
            throw alpinocorpus::Error(e.what());
        }
        return self.r == other.r;
    } catch (std::bad_cast const &e) {
        return false;
    }
}

/* operator++ */
void DbCorpusReaderPrivate::DbIter::next()
{
    try {
        db::XmlDocument doc;
        r.next(doc);
    } catch (db::XmlException const &e) {
        throw alpinocorpus::Error(e.what());
    }
}

DbCorpusReaderPrivate::QueryIter::QueryIter(db::XmlResults const &r)
 : DbIter(r)
{
}

QString DbCorpusReaderPrivate::QueryIter::contents(CorpusReader const &) const
{
    db::XmlValue v;
    r.peek(v);
    return toQString(v.getNodeValue());
}

CorpusReader::EntryIterator DbCorpusReader::getBegin() const
{
    return d_private->getBegin();
}

CorpusReader::EntryIterator DbCorpusReader::getEnd() const
{
    return d_private->getEnd();
}

size_t DbCorpusReader::getSize() const
{
    return d_private->getSize();
}

bool DbCorpusReader::validQuery(QueryDialect d, bool variables, QString const &query) const
{
    return d_private->isValidQuery(d, variables, query);
}

QString DbCorpusReader::readEntry(const QString &entry) const
{
    return d_private->readEntry(entry);
}

QString DbCorpusReader::readEntryMarkQuery(QString const &entry, QueryDialect d, QString const &query,
    QString const &attr, QString const &value) const
{
    return d_private->readEntryMarkQuery(entry, d, query, attr, value);
}

CorpusReader::EntryIterator DbCorpusReader::runXPath(QString const &query) const
{
    return d_private->runXPath(query);
}

CorpusReader::EntryIterator DbCorpusReader::runXQuery(QString const &query) const
{
    return d_private->runXQuery(query);
}

DbCorpusReaderPrivate::DbCorpusReaderPrivate(QString const &qpath)
 : mgr(), container()
{
    std::string path(qpath.toLocal8Bit().data());

    try {
        db::XmlContainerConfig config;
        config.setReadOnly(true);
        container = mgr.openContainer(path, config);
        // Nasty: using a hard-coded alias to work use in the xpath queries.
        container.addAlias("corpus");
        setNameAndCollection(qpath);
    } catch (db::XmlException const &e) {
        throw OpenError(qpath, QString::fromUtf8(e.what()));
    }
}

DbCorpusReaderPrivate::~DbCorpusReaderPrivate()
{
}

CorpusReader::EntryIterator DbCorpusReaderPrivate::getBegin() const
{
    return EntryIterator(new DbIter(container));
}

CorpusReader::EntryIterator DbCorpusReaderPrivate::getEnd() const
{
    return EntryIterator(new DbIter(mgr));
}

bool DbCorpusReaderPrivate::validQuery(QueryDialect d, bool variables, QString const &query) const
{
    try {
        db::XmlQueryContext ctx = mgr.createQueryContext();
        QByteArray queryData(query.toUtf8());
        mgr.prepare(queryData.constData(), ctx);
    } catch (db::XmlException const &e) {
        return false;
    }

    return true;
}

QString DbCorpusReaderPrivate::readEntry(QString const &filename) const
{
    std::string name(filename.toUtf8().data());

    try {
        db::XmlDocument doc(container.getDocument(name, db::DBXML_LAZY_DOCS));
        std::string content;
        return toQString(doc.getContent(content));

    } catch (db::XmlException const &e) {
        std::ostringstream msg;
        msg << "entry \""                  << name
            << "\" cannot be read from \"" << container.getName()
            << "\" ("                      << e.what()
            << ")";
        throw Error(msg.str());
    }
}

QString DbCorpusReaderPrivate::readEntryMarkQuery(QString const &entry, QueryDialect d, QString const &query,
    QString const &attr, QString const &value) const
{
    std::string name(entry.toUtf8().data());
    std::string content;
    QByteArray attrArray(attr.toUtf8());
    QByteArray valArray(value.toUtf8());

    try {
        db::XmlDocument doc(container.getDocument(name, db::DBXML_LAZY_DOCS));
        doc.getContent(content);
    } catch (db::XmlException const &e) {
        std::ostringstream msg;
        msg << "entry \""                  << name
        << "\" cannot be read from \"" << container.getName()
        << "\" ("                      << e.what()
        << ")";
        throw Error(msg.str());
    }

    QByteArray utf8Query(query.toUtf8());

    // Prepare the DOM parser.
    xerces::DOMImplementation *xqillaImplementation =
        xerces::DOMImplementationRegistry::getDOMImplementation(X("XPath2 3.0"));
    AutoRelease<xerces::DOMLSParser> parser(xqillaImplementation->createLSParser(
        xerces::DOMImplementationLS::MODE_SYNCHRONOUS, 0));

    // Parse the document.
    xerces::MemBufInputSource xmlInput(reinterpret_cast<XMLByte const *>(content.c_str()),
        content.size(), "input");

    xerces::Wrapper4InputSource domInput(&xmlInput, false);

    xerces::DOMDocument *document;
    try {
        document = parser->parse(&domInput);
    } catch (xerces::DOMException const &e) {
        throw Error(std::string("Could not parse XML data: ") + UTF8(e.getMessage()));
    }

    AutoRelease<xerces::DOMXPathExpression> expression(0);
    try {
        expression.set(document->createExpression(X(utf8Query.constData()), 0));
    } catch (xerces::DOMXPathException const &) {
        throw Error("Could not parse expression.");
    } catch (xerces::DOMException const &) {
        throw Error("Could not resolve namespace prefixes.");
    }

    AutoRelease<xerces::DOMXPathResult> result(0);
    try {
        result.set(expression->evaluate(document,
            xerces::DOMXPathResult::ITERATOR_RESULT_TYPE, 0));
    } catch (xerces::DOMXPathException const &e) {
        throw Error("Could not retrieve an iterator over evaluation results.");
    } catch (xerces::DOMException &e) {
        throw Error("Could not evaluate the expression on the given document.");
    }

    QList<xerces::DOMNode *> markNodes;

    while (result->iterateNext())
    {
        xerces::DOMNode *node = result->getNodeValue();

        // Skip non-element nodes
        if (node->getNodeType() != xerces::DOMNode::ELEMENT_NODE)
            continue;

        markNodes.append(node);
    }

    for (QList<xerces::DOMNode *>::iterator iter = markNodes.begin();
         iter != markNodes.end(); ++iter)
    {
        xerces::DOMNode *node = *iter;

        xerces::DOMNamedNodeMap *map = node->getAttributes();
        if (map == 0)
            continue;

        // Create new attribute node.
        xerces::DOMAttr *attr;
        try {
            attr = document->createAttribute(X(attrArray.constData()));
        } catch (xerces::DOMException const &e) {
            throw Error("Attribute name contains invalid character.");
        }
        attr->setNodeValue(X(valArray.constData()));

        map->setNamedItem(attr);

    }

    // Serialize DOM tree
    AutoRelease<xerces::DOMLSSerializer> serializer(xqillaImplementation->createLSSerializer());
    AutoRelease<xerces::DOMLSOutput> output(xqillaImplementation->createLSOutput());
    xerces::MemBufFormatTarget target;
    output->setByteStream(&target);
    serializer->write(document, output.get());

    QByteArray outArray(reinterpret_cast<char const *>(target.getRawBuffer()),
        target.getLen());

    return QString::fromUtf8(outArray);
}

CorpusReader::EntryIterator DbCorpusReaderPrivate::runXPath(QString const &query) const
{
    return runXQuery(QString("collection('corpus')" + query));
}

CorpusReader::EntryIterator DbCorpusReaderPrivate::runXQuery(QString const &query)
    const
{
    // XXX use DBXML_DOCUMENT_PROJECTION and return to whole-doc containers?

    try {
        db::XmlQueryContext ctx
            = mgr.createQueryContext(db::XmlQueryContext::LiveValues,
                                     db::XmlQueryContext::Lazy);
        ctx.setDefaultCollection(collection);
        db::XmlResults r(mgr.query(query.toUtf8().data(), ctx,
                                     db::DBXML_LAZY_DOCS
                                   | db::DBXML_WELL_FORMED_ONLY
                                  ));
        return EntryIterator(new QueryIter(r));
    } catch (db::XmlException const &e) {
        throw alpinocorpus::Error(e.what());
    }
}

/*
 * Set corpus name to container name; set collection to a usable collection
 * name.
 *
 * The collection name is used for querying. We set it to the absolute path
 * so we can still run queries after a chdir().
 * For some reason, DB XML strips off a leading slash in the filename,
 * so we prepend an extra one.
 */
void DbCorpusReaderPrivate::setNameAndCollection(QString const &path)
{
    //collection = QFileInfo(path).absoluteFilePath().toLocal8Bit().data();

    setName(toQString(container.getName()));

    collection = std::string("/") + name().toLocal8Bit().data();
}

}   // namespace alpinocorpus
<|endoftext|>


<commit_before>/**
 * This file is part of the "FnordMetric" project
 *   Copyright (c) 2014 Paul Asmuth, Google Inc.
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include <chartsql/runtime/SelectExpression.h>

namespace csql {

SelectExpression::SelectExpression(
    const Vector<String>& column_names,
    Vector<ScopedPtr<ValueExpression>> select_expressions) :
    column_names_(column_names),
    select_exprs_(std::move(select_expressions)) {}

void SelectExpression::execute(
    ExecutionContext* context,
    Function<bool (int argc, const SValue* argv)> fn) {
  Vector<SValue> out_row(select_exprs_.size(), SValue{});

  for (int i = 0; i < select_exprs_.size(); ++i) {
    select_exprs_[i]->evaluate(0, nullptr,  &out_row[i]);
  }

  fn(out_row.size(), out_row.data());
}

Vector<String> SelectExpression::columnNames() const {
  return column_names_;
}

size_t SelectExpression::numColumns() const {
  return column_names_.size();
}

}
<commit_msg>use new VM iface in SelectExpression<commit_after>/**
 * This file is part of the "FnordMetric" project
 *   Copyright (c) 2014 Paul Asmuth, Google Inc.
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include <chartsql/runtime/SelectExpression.h>

namespace csql {

SelectExpression::SelectExpression(
    const Vector<String>& column_names,
    Vector<ScopedPtr<ValueExpression>> select_expressions) :
    column_names_(column_names),
    select_exprs_(std::move(select_expressions)) {}

void SelectExpression::execute(
    ExecutionContext* context,
    Function<bool (int argc, const SValue* argv)> fn) {
  Vector<SValue> out_row(select_exprs_.size(), SValue{});

  for (int i = 0; i < select_exprs_.size(); ++i) {
    VM::evaluate(select_exprs_[i]->program(), 0, nullptr,  &out_row[i]);
  }

  fn(out_row.size(), out_row.data());
}

Vector<String> SelectExpression::columnNames() const {
  return column_names_;
}

size_t SelectExpression::numColumns() const {
  return column_names_.size();
}

}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: MNSTerminateListener.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: hjs $ $Date: 2004-06-25 18:32:55 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _MNSTERMINATELISTENER_HXX
#include <MNSTerminateListener.hxx>
#endif
#ifndef _COMPHELPER_PROCESSFACTORY_HXX_
#include <comphelper/processfactory.hxx>
#endif
#ifndef _COM_SUN_STAR_FRAME_XDESKTOP_HPP_
#include <com/sun/star/frame/XDesktop.hpp>
#endif
#ifndef _CONNECTIVITY_MAB_NS_INIT_HXX_
#include <MNSInit.hxx>
#endif

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::frame;
::com::sun::star::uno::Reference< ::com::sun::star::frame::XTerminateListener>          MNSTerminateListener::mxTerminateListener = new MNSTerminateListener();

// -----------------------------------------
// - MNSTerminateListener -
// -----------------------------------------

MNSTerminateListener::MNSTerminateListener(  )
{
}

// -----------------------------------------------------------------------------

MNSTerminateListener::~MNSTerminateListener()
{
}

// -----------------------------------------------------------------------------

void SAL_CALL MNSTerminateListener::disposing( const EventObject& Source ) throw( RuntimeException )
{
}

// -----------------------------------------------------------------------------

void SAL_CALL MNSTerminateListener::queryTermination( const EventObject& aEvent ) throw( TerminationVetoException, RuntimeException )
{
}

// -----------------------------------------------------------------------------

void SAL_CALL MNSTerminateListener::notifyTermination( const EventObject& aEvent ) throw( RuntimeException )
{
    MNS_Term(sal_True); //Force XPCOM to shutdown
}

void MNSTerminateListener::addTerminateListener()
{
    Reference< XMultiServiceFactory >   xFact( ::comphelper::getProcessServiceFactory() );

    if( xFact.is() )
    {
        Reference< XDesktop > xDesktop( xFact->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.frame.Desktop" ) ), UNO_QUERY );

        if( xDesktop.is() )
            xDesktop->addTerminateListener(mxTerminateListener);
    }
}

<commit_msg>INTEGRATION: CWS ooo19126 (1.2.138); FILE MERGED 2005/09/05 17:24:35 rt 1.2.138.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: MNSTerminateListener.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 06:28:34 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _MNSTERMINATELISTENER_HXX
#include <MNSTerminateListener.hxx>
#endif
#ifndef _COMPHELPER_PROCESSFACTORY_HXX_
#include <comphelper/processfactory.hxx>
#endif
#ifndef _COM_SUN_STAR_FRAME_XDESKTOP_HPP_
#include <com/sun/star/frame/XDesktop.hpp>
#endif
#ifndef _CONNECTIVITY_MAB_NS_INIT_HXX_
#include <MNSInit.hxx>
#endif

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::frame;
::com::sun::star::uno::Reference< ::com::sun::star::frame::XTerminateListener>          MNSTerminateListener::mxTerminateListener = new MNSTerminateListener();

// -----------------------------------------
// - MNSTerminateListener -
// -----------------------------------------

MNSTerminateListener::MNSTerminateListener(  )
{
}

// -----------------------------------------------------------------------------

MNSTerminateListener::~MNSTerminateListener()
{
}

// -----------------------------------------------------------------------------

void SAL_CALL MNSTerminateListener::disposing( const EventObject& Source ) throw( RuntimeException )
{
}

// -----------------------------------------------------------------------------

void SAL_CALL MNSTerminateListener::queryTermination( const EventObject& aEvent ) throw( TerminationVetoException, RuntimeException )
{
}

// -----------------------------------------------------------------------------

void SAL_CALL MNSTerminateListener::notifyTermination( const EventObject& aEvent ) throw( RuntimeException )
{
    MNS_Term(sal_True); //Force XPCOM to shutdown
}

void MNSTerminateListener::addTerminateListener()
{
    Reference< XMultiServiceFactory >   xFact( ::comphelper::getProcessServiceFactory() );

    if( xFact.is() )
    {
        Reference< XDesktop > xDesktop( xFact->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.frame.Desktop" ) ), UNO_QUERY );

        if( xDesktop.is() )
            xDesktop->addTerminateListener(mxTerminateListener);
    }
}

<|endoftext|>


<commit_before>///
/// @file   main.cpp
/// @brief  primecount console application.
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include "cmdoptions.hpp"

#include <primecount.hpp>
#include <primecount-internal.hpp>
#include <calculator.hpp>
#include <imath.hpp>
#include <int128_t.hpp>
#include <PhiTiny.hpp>
#include <S1.hpp>
#include <S2.hpp>

#include <stdint.h>
#include <exception>
#include <iostream>
#include <limits>
#include <string>

#ifdef HAVE_MPI
  #include <mpi.h>
#endif

using namespace std;
using namespace primecount;

namespace primecount {

int64_t to_int64(maxint_t x)
{
  if (x > numeric_limits<int64_t>::max())
    throw primecount_error("this is a 63-bit function, x must be < 2^63");
  return (int64_t) x;
}

maxint_t P2(maxint_t x, int threads)
{
  if (x < 1)
    return 0;

  double alpha = get_alpha_deleglise_rivat(x);
  string limit = get_max_x(alpha);

  if (x > to_maxint(limit))
    throw primecount_error("P2(x): x must be <= " + limit);

  if (print_status())
    set_print_variables(true);

  int64_t y = (int64_t) (iroot<3>(x) * alpha);

  if (x <= numeric_limits<int64_t>::max())
    return P2((int64_t) x, y, threads);
  else
    return P2(x, y, threads);
}

maxint_t S1(maxint_t x, int threads)
{
  if (x < 1)
    return 0;

  double alpha = get_alpha_deleglise_rivat(x);
  string limit = get_max_x(alpha);

  if (x > to_maxint(limit))
    throw primecount_error("S1(x): x must be <= " + limit);

  if (print_status())
    set_print_variables(true);

  int64_t y = (int64_t) (iroot<3>(x) * alpha);
  int64_t c = PhiTiny::get_c(y);

  if (x <= numeric_limits<int64_t>::max())
    return S1((int64_t) x, y, c, threads);
  else
    return S1(x, y, c, threads);
}

maxint_t S2_trivial(maxint_t x, int threads)
{
  if (x < 1)
    return 0;

  double alpha = get_alpha_deleglise_rivat(x);
  string limit = get_max_x(alpha);

  if (x > to_maxint(limit))
    throw primecount_error("S2_trivial(x): x must be <= " + limit);

  if (print_status())
    set_print_variables(true);

  int64_t y = (int64_t) (iroot<3>(x) * alpha);
  int64_t z = (int64_t) (x / y);
  int64_t c = PhiTiny::get_c(y);

  if (x <= numeric_limits<int64_t>::max())
    return S2_trivial((int64_t) x, y, z, c, threads);
  else
    return S2_trivial(x, y, z, c, threads);
}

maxint_t S2_easy(maxint_t x, int threads)
{
  if (x < 1)
    return 0;

  double alpha = get_alpha_deleglise_rivat(x);
  string limit = get_max_x(alpha);

  if (x > to_maxint(limit))
    throw primecount_error("S2_easy(x): x must be <= " + limit);

  if (print_status())
    set_print_variables(true);

  int64_t y = (int64_t) (iroot<3>(x) * alpha);
  int64_t z = (int64_t) (x / y);
  int64_t c = PhiTiny::get_c(y);

  if (x <= numeric_limits<int64_t>::max())
    return S2_easy((int64_t) x, y, z, c, threads);
  else
    return S2_easy(x, y, z, c, threads);
}

maxint_t S2_hard(maxint_t x, int threads)
{
  if (x < 1)
    return 0;

  double alpha = get_alpha_deleglise_rivat(x);
  string limit = get_max_x(alpha);

  if (x > to_maxint(limit))
    throw primecount_error("S2_hard(x): x must be <= " + limit);

  if (print_status())
    set_print_variables(true);

  int64_t y = (int64_t) (iroot<3>(x) * alpha);
  int64_t z = (int64_t) (x / y);
  int64_t c = PhiTiny::get_c(y);

  // TODO: find better S2_hard approximation formula
  maxint_t s2_hard_approx = Ri(x);

  if (x <= numeric_limits<int64_t>::max())
    return S2_hard((int64_t) x, y, z, c, (int64_t) s2_hard_approx, threads);
  else
    return S2_hard(x, y, z, c, s2_hard_approx, threads);
}

} // namespace

int main (int argc, char* argv[])
{
#ifdef HAVE_MPI
  MPI_Init(&argc, &argv);
#endif

  try
  {
    CmdOptions opt = parseOptions(argc, argv);
    double time = get_wtime();

    maxint_t x = opt.x;
    maxint_t res = 0;
    int threads = opt.threads;

    switch (opt.option)
    {
      case OPTION_DELEGLISE_RIVAT:
        res = pi_deleglise_rivat(x, threads); break;
      case OPTION_DELEGLISE_RIVAT1:
        res = pi_deleglise_rivat1(to_int64(x)); break;
      case OPTION_DELEGLISE_RIVAT2:
        res = pi_deleglise_rivat2(to_int64(x)); break;
      case OPTION_DELEGLISE_RIVAT_PARALLEL1:
        res = pi_deleglise_rivat_parallel1(to_int64(x), threads); break;
      case OPTION_DELEGLISE_RIVAT_PARALLEL2:
        res = pi_deleglise_rivat_parallel2(to_int64(x), threads); break;
      case OPTION_LEGENDRE:
        res = pi_legendre(to_int64(x), threads); break;
      case OPTION_LEHMER:
        res = pi_lehmer(to_int64(x), threads); break;
      case OPTION_LMO:
        res = pi_lmo(to_int64(x), threads); break;
      case OPTION_LMO1:
        res = pi_lmo1(to_int64(x)); break;
      case OPTION_LMO2:
        res = pi_lmo2(to_int64(x)); break;
      case OPTION_LMO3:
        res = pi_lmo3(to_int64(x)); break;
      case OPTION_LMO4:
        res = pi_lmo4(to_int64(x)); break;
      case OPTION_LMO5:
        res = pi_lmo5(to_int64(x)); break;
      case OPTION_LMO_PARALLEL1:
        res = pi_lmo_parallel1(to_int64(x), threads); break;
      case OPTION_LMO_PARALLEL2:
        res = pi_lmo_parallel2(to_int64(x), threads); break;
      case OPTION_LMO_PARALLEL3:
        res = pi_lmo_parallel3(to_int64(x), threads); break;
      case OPTION_MEISSEL:
        res = pi_meissel(to_int64(x), threads); break;
      case OPTION_PRIMESIEVE:
        res = pi_primesieve(to_int64(x), threads); break;
      case OPTION_P2:
        res = P2(x, threads); break;
      case OPTION_PI:
        res = pi(x, threads); break;
      case OPTION_LI:
        res = Li(to_int64(x)); break;
      case OPTION_LIINV:
        res = Li_inverse(to_int64(x)); break;
      case OPTION_RI:
        res = Ri(to_int64(x)); break;
      case OPTION_RIINV:
        res = Ri_inverse(to_int64(x)); break;
      case OPTION_NTHPRIME:
        res = nth_prime(to_int64(x), threads); break;
      case OPTION_S1:
        res = S1(x, threads); break;
      case OPTION_S2_EASY:
        res = S2_easy(x, threads); break;
      case OPTION_S2_HARD:
        res = S2_hard(x, threads); break;
      case OPTION_S2_TRIVIAL:
        res = S2_trivial(x, threads); break;
#ifdef HAVE_INT128_T
      case OPTION_DELEGLISE_RIVAT_PARALLEL3:
        res = pi_deleglise_rivat_parallel3(x, threads); break;
#endif
    }

    if (print_result())
    {
      if (print_status())
        cout << endl;
      cout << res << endl;
      if (opt.time)
        print_seconds(get_wtime() - time);
    }
  }
  catch (calculator::error& e)
  {
#ifdef HAVE_MPI
    MPI_Finalize();
#endif
    cerr << e.what() << "." << endl
         << "Try `primecount --help' for more information." << endl;
    return 1;
  }
  catch (exception& e)
  {
#ifdef HAVE_MPI
    MPI_Finalize();
#endif
    cerr << "Error: " << e.what() << "." << endl
         << "Try `primecount --help' for more information." << endl;
    return 1;
  }

#ifdef HAVE_MPI
    MPI_Finalize();
#endif

  return 0;
}
<commit_msg>128-bit Li(x) & Ri(x)<commit_after>///
/// @file   main.cpp
/// @brief  primecount console application.
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include "cmdoptions.hpp"

#include <primecount.hpp>
#include <primecount-internal.hpp>
#include <calculator.hpp>
#include <imath.hpp>
#include <int128_t.hpp>
#include <PhiTiny.hpp>
#include <S1.hpp>
#include <S2.hpp>

#include <stdint.h>
#include <exception>
#include <iostream>
#include <limits>
#include <string>

#ifdef HAVE_MPI
  #include <mpi.h>
#endif

using namespace std;
using namespace primecount;

namespace primecount {

int64_t to_int64(maxint_t x)
{
  if (x > numeric_limits<int64_t>::max())
    throw primecount_error("this is a 63-bit function, x must be < 2^63");
  return (int64_t) x;
}

maxint_t P2(maxint_t x, int threads)
{
  if (x < 1)
    return 0;

  double alpha = get_alpha_deleglise_rivat(x);
  string limit = get_max_x(alpha);

  if (x > to_maxint(limit))
    throw primecount_error("P2(x): x must be <= " + limit);

  if (print_status())
    set_print_variables(true);

  int64_t y = (int64_t) (iroot<3>(x) * alpha);

  if (x <= numeric_limits<int64_t>::max())
    return P2((int64_t) x, y, threads);
  else
    return P2(x, y, threads);
}

maxint_t S1(maxint_t x, int threads)
{
  if (x < 1)
    return 0;

  double alpha = get_alpha_deleglise_rivat(x);
  string limit = get_max_x(alpha);

  if (x > to_maxint(limit))
    throw primecount_error("S1(x): x must be <= " + limit);

  if (print_status())
    set_print_variables(true);

  int64_t y = (int64_t) (iroot<3>(x) * alpha);
  int64_t c = PhiTiny::get_c(y);

  if (x <= numeric_limits<int64_t>::max())
    return S1((int64_t) x, y, c, threads);
  else
    return S1(x, y, c, threads);
}

maxint_t S2_trivial(maxint_t x, int threads)
{
  if (x < 1)
    return 0;

  double alpha = get_alpha_deleglise_rivat(x);
  string limit = get_max_x(alpha);

  if (x > to_maxint(limit))
    throw primecount_error("S2_trivial(x): x must be <= " + limit);

  if (print_status())
    set_print_variables(true);

  int64_t y = (int64_t) (iroot<3>(x) * alpha);
  int64_t z = (int64_t) (x / y);
  int64_t c = PhiTiny::get_c(y);

  if (x <= numeric_limits<int64_t>::max())
    return S2_trivial((int64_t) x, y, z, c, threads);
  else
    return S2_trivial(x, y, z, c, threads);
}

maxint_t S2_easy(maxint_t x, int threads)
{
  if (x < 1)
    return 0;

  double alpha = get_alpha_deleglise_rivat(x);
  string limit = get_max_x(alpha);

  if (x > to_maxint(limit))
    throw primecount_error("S2_easy(x): x must be <= " + limit);

  if (print_status())
    set_print_variables(true);

  int64_t y = (int64_t) (iroot<3>(x) * alpha);
  int64_t z = (int64_t) (x / y);
  int64_t c = PhiTiny::get_c(y);

  if (x <= numeric_limits<int64_t>::max())
    return S2_easy((int64_t) x, y, z, c, threads);
  else
    return S2_easy(x, y, z, c, threads);
}

maxint_t S2_hard(maxint_t x, int threads)
{
  if (x < 1)
    return 0;

  double alpha = get_alpha_deleglise_rivat(x);
  string limit = get_max_x(alpha);

  if (x > to_maxint(limit))
    throw primecount_error("S2_hard(x): x must be <= " + limit);

  if (print_status())
    set_print_variables(true);

  int64_t y = (int64_t) (iroot<3>(x) * alpha);
  int64_t z = (int64_t) (x / y);
  int64_t c = PhiTiny::get_c(y);

  // TODO: find better S2_hard approximation formula
  maxint_t s2_hard_approx = Ri(x);

  if (x <= numeric_limits<int64_t>::max())
    return S2_hard((int64_t) x, y, z, c, (int64_t) s2_hard_approx, threads);
  else
    return S2_hard(x, y, z, c, s2_hard_approx, threads);
}

} // namespace

int main (int argc, char* argv[])
{
#ifdef HAVE_MPI
  MPI_Init(&argc, &argv);
#endif

  try
  {
    CmdOptions opt = parseOptions(argc, argv);
    double time = get_wtime();

    maxint_t x = opt.x;
    maxint_t res = 0;
    int threads = opt.threads;

    switch (opt.option)
    {
      case OPTION_DELEGLISE_RIVAT:
        res = pi_deleglise_rivat(x, threads); break;
      case OPTION_DELEGLISE_RIVAT1:
        res = pi_deleglise_rivat1(to_int64(x)); break;
      case OPTION_DELEGLISE_RIVAT2:
        res = pi_deleglise_rivat2(to_int64(x)); break;
      case OPTION_DELEGLISE_RIVAT_PARALLEL1:
        res = pi_deleglise_rivat_parallel1(to_int64(x), threads); break;
      case OPTION_DELEGLISE_RIVAT_PARALLEL2:
        res = pi_deleglise_rivat_parallel2(to_int64(x), threads); break;
      case OPTION_LEGENDRE:
        res = pi_legendre(to_int64(x), threads); break;
      case OPTION_LEHMER:
        res = pi_lehmer(to_int64(x), threads); break;
      case OPTION_LMO:
        res = pi_lmo(to_int64(x), threads); break;
      case OPTION_LMO1:
        res = pi_lmo1(to_int64(x)); break;
      case OPTION_LMO2:
        res = pi_lmo2(to_int64(x)); break;
      case OPTION_LMO3:
        res = pi_lmo3(to_int64(x)); break;
      case OPTION_LMO4:
        res = pi_lmo4(to_int64(x)); break;
      case OPTION_LMO5:
        res = pi_lmo5(to_int64(x)); break;
      case OPTION_LMO_PARALLEL1:
        res = pi_lmo_parallel1(to_int64(x), threads); break;
      case OPTION_LMO_PARALLEL2:
        res = pi_lmo_parallel2(to_int64(x), threads); break;
      case OPTION_LMO_PARALLEL3:
        res = pi_lmo_parallel3(to_int64(x), threads); break;
      case OPTION_MEISSEL:
        res = pi_meissel(to_int64(x), threads); break;
      case OPTION_PRIMESIEVE:
        res = pi_primesieve(to_int64(x), threads); break;
      case OPTION_P2:
        res = P2(x, threads); break;
      case OPTION_PI:
        res = pi(x, threads); break;
      case OPTION_LI:
        res = Li(x); break;
      case OPTION_LIINV:
        res = Li_inverse(x); break;
      case OPTION_RI:
        res = Ri(x); break;
      case OPTION_RIINV:
        res = Ri_inverse(x); break;
      case OPTION_NTHPRIME:
        res = nth_prime(to_int64(x), threads); break;
      case OPTION_S1:
        res = S1(x, threads); break;
      case OPTION_S2_EASY:
        res = S2_easy(x, threads); break;
      case OPTION_S2_HARD:
        res = S2_hard(x, threads); break;
      case OPTION_S2_TRIVIAL:
        res = S2_trivial(x, threads); break;
#ifdef HAVE_INT128_T
      case OPTION_DELEGLISE_RIVAT_PARALLEL3:
        res = pi_deleglise_rivat_parallel3(x, threads); break;
#endif
    }

    if (print_result())
    {
      if (print_status())
        cout << endl;
      cout << res << endl;
      if (opt.time)
        print_seconds(get_wtime() - time);
    }
  }
  catch (calculator::error& e)
  {
#ifdef HAVE_MPI
    MPI_Finalize();
#endif
    cerr << e.what() << "." << endl
         << "Try `primecount --help' for more information." << endl;
    return 1;
  }
  catch (exception& e)
  {
#ifdef HAVE_MPI
    MPI_Finalize();
#endif
    cerr << "Error: " << e.what() << "." << endl
         << "Try `primecount --help' for more information." << endl;
    return 1;
  }

#ifdef HAVE_MPI
    MPI_Finalize();
#endif

  return 0;
}
<|endoftext|>


<commit_before>#pragma once

class Extracting_agent {
public:
  Extracting_agent() = delete;
  Extracting_agent(const std::string& inbmp);

  std::string extract(int num_lsb) {
    return "";
  }
private:
  dgbmp input;
  int num_lsb;
}
<commit_msg>Added const<commit_after>#pragma once

class Extracting_agent {
public:
  Extracting_agent() = delete;
  Extracting_agent(const std::string& inbmp);

  std::string extract(int num_lsb) const;
private:
  dgbmp input;
  int num_lsb;
};
<|endoftext|>


<commit_before>#include <ros/ros.h>
#include <humanoid_catching/CalculateTorques.h>
#include <Moby/qpOASES.h>
#include <Ravelin/VectorNd.h>
#include <Ravelin/MatrixNd.h>
#include <Ravelin/Quatd.h>
#include <Ravelin/Opsd.h>
#include <Moby/qpOASES.h>

namespace {
using namespace std;
using namespace humanoid_catching;

static const double GRAVITY = 9.81;

class Balancer {
private:
    //! Node handle
    ros::NodeHandle nh;

    //! Private nh
    ros::NodeHandle pnh;

    //! Balancer Service
    ros::ServiceServer balancerService;

public:
   Balancer() :
     pnh("~") {

       balancerService = nh.advertiseService("/balancer/calculate_torques",
            &Balancer::calculateTorques, this);
	}

private:

    static Ravelin::Vector3d toVector(const geometry_msgs::Vector3& v3) {
        Ravelin::Vector3d v;
        v[0] = v3.x;
        v[1] = v3.y;
        v[2] = v3.z;
        return v;
    }

    static Ravelin::Vector3d toVector(const geometry_msgs::Point& p) {
        Ravelin::Vector3d v;
        v[0] = p.x;
        v[1] = p.y;
        v[2] = p.z;
        return v;
    }

    bool calculateTorques(humanoid_catching::CalculateTorques::Request& req,
               humanoid_catching::CalculateTorques::Response& res) {

      ROS_INFO("Calculating torques frame %s", req.header.frame_id.c_str());

      // x
      // linear velocity of body
      Ravelin::Vector3d x = toVector(req.body_velocity.linear);

      // w
      // angular velocity of body
      Ravelin::Vector3d w = toVector(req.body_velocity.angular);

      // v(t)
      // | x |
      // | w |
      Ravelin::VectorNd v(6);
      v.set_sub_vec(0, x);
      v.set_sub_vec(3, w);

      // R
      // Pole rotation matrix
      Ravelin::Matrix3d R = Ravelin::MatrixNd(Ravelin::Quatd(req.body_com.orientation.x, req.body_com.orientation.y, req.body_com.orientation.z, req.body_com.orientation.w));

      // J
      // Pole inertia matrix
      Ravelin::Matrix3d J = Ravelin::MatrixNd(&req.body_inertia_matrix[0]);

      // JRobot
      // Robot jacobian matrix
      Ravelin::Matrix3d JRobot = Ravelin::MatrixNd(&req.jacobian_matrix[0]);

      // 3x3 working matrix
      Ravelin::Matrix3d temp;

      // RJR_t
      Ravelin::Matrix3d RJR = R.mult(J, temp).mult(Ravelin::Matrix3d::transpose(R), temp);

      // M
      // | Im   0 |
      // | 0 RJR_t|
      Ravelin::MatrixNd M(6, 6);
      M.set_zero(M.rows(), M.columns());
      M.set_sub_mat(0, 0, Ravelin::Matrix3d::identity() * req.body_mass);
      M.set_sub_mat(3, 3, RJR);

      // delta t
      double deltaT = req.time_delta.toSec();

      // Working vector
      Ravelin::Vector3d tempVector;

      // fext
      // | g           |
      // | -w x RJR_tw |
      Ravelin::VectorNd fExt(6);
      fExt[0] = 0;
      fExt[1] = 0;
      fExt[2] = GRAVITY;
      fExt.set_sub_vec(3, Ravelin::Vector3d::cross(-w, RJR.mult(w, tempVector)));

      // n_hat
      // x component of ground contact position
      Ravelin::Vector3d nHat;
      nHat[0] = req.ground_contact.x;
      nHat[1] = 0;
      nHat[2] = 0;

      // s_hat
      // s component of contact position
      Ravelin::Vector3d sHat;
      nHat[0] = 0;
      nHat[1] = req.ground_contact.y;
      nHat[2] = 0;

      // t_hat
      // z component of contact position
      Ravelin::Vector3d tHat;
      tHat[0] = 0;
      tHat[1] = 0;
      tHat[2] = req.ground_contact.z;

      // q_hat
      // contact normal
      Ravelin::Vector3d qHat = toVector(req.contact_normal);

      // p
      // contact point
      Ravelin::Vector3d p = toVector(req.ground_contact);

      // x_bar
      // pole COM
      Ravelin::Vector3d xBar = toVector(req.body_com.position);

      // r
      Ravelin::Vector3d r = p - xBar;

      // N
      // | n_hat     |
      // | r x n_hat |
      Ravelin::VectorNd N(6);
      N.set_sub_vec(0, nHat);
      N.set_sub_vec(3, r.cross(nHat, tempVector));

      // S
      // | s_hat     |
      // | r x s_hat |
      Ravelin::VectorNd S(6);
      S.set_sub_vec(0, sHat);
      S.set_sub_vec(3, r.cross(sHat, tempVector));

      // T
      // | t_hat     |
      // | r x t_hat |
      Ravelin::VectorNd T(6);
      T.set_sub_vec(0, tHat);
      T.set_sub_vec(3, r.cross(tHat, tempVector));

      // Q
      Ravelin::VectorNd Q(6);
      Q.set_sub_vec(0, qHat);
      Q.set_sub_vec(3, -r.cross(qHat, tempVector));

      // Result vector
      // Torques, f_n, f_s, f_t, f_robot, v_t
      Ravelin::VectorNd z(req.torque_limits.size() + 1 + 1 + 1 + 1 + 6);

      // Set up minimization function
      Ravelin::MatrixNd H(6, 6);
      Ravelin::VectorNd c(6);
      c.set_zero(c.rows());

      // Linear equality constraints
      Ravelin::MatrixNd A(6 * 2 + req.torque_limits.size(), z.size());
      Ravelin::VectorNd b(6 * 2 + req.torque_limits.size());

      // Sv(t) = 0 (no tangent velocity)
      A.set_sub_mat(0, req.torque_limits.size() + 6 * 4, S);
      b.set_sub_vec(0, Ravelin::VectorNd::zero(6));

      // Tv(t) = 0 (no tangent velocity)
      A.set_sub_mat(6, req.torque_limits.size() + 6 * 4, T);
      b.set_sub_vec(6, Ravelin::VectorNd::zero(6));

      // J_robot(transpose) * Q(transpose) * f_robot = torques
      Ravelin::MatrixNd JQ(req.torque_limits.size(), 1);
      Ravelin::MatrixNd Jt(JRobot.columns(), JRobot.rows());
      JRobot.transpose(Jt);
      Ravelin::MatrixNd::mult(Jt, Ravelin::MatrixNd(Q, Ravelin::eTranspose), JQ);
      A.set_sub_mat(6 * 2, req.torque_limits.size() + 3, JQ);
      A.set_sub_mat(6 * 2, 0, Ravelin::MatrixNd::identity(req.torque_limits.size()).negate());
      b.set_sub_vec(6 * 2, Ravelin::VectorNd::zero(7));

      // Linear inequality constraints
      Ravelin::MatrixNd Mc(6, z.size());
      Ravelin::VectorNd q(6);

      // Nv(t) >= 0 (non-negative normal velocity)
      Mc.set_sub_mat(0, req.torque_limits.size() + 6 * 4, N);
      q.set_sub_vec(0, Ravelin::VectorNd::zero(6));

      // Solution variable constraint
      Ravelin::VectorNd lb(z.size());
      Ravelin::VectorNd ub(z.size());

      // Torque constraints
      unsigned int bound = 0;
      for (bound; bound < req.torque_limits.size(); ++bound) {
        lb[bound] = req.torque_limits[bound].minimum;
        ub[bound] = req.torque_limits[bound].maximum;
      }

      // f_n >= 0
      lb[bound] = 0;
      ub[bound] = INFINITY;
      ++bound;

      // f_s (no constraints)
      lb[bound] = INFINITY;
      ub[bound] = INFINITY;
      ++bound;

      // f_t (no constraints)
      lb[bound] = INFINITY;
      ub[bound] = INFINITY;
      ++bound;

      // f_robot >= 0
      lb[bound] = INFINITY;
      ub[bound] = INFINITY;
      ++bound;

      // v_t (no constraints)
      for (bound; bound < z.size(); ++bound) {
        lb[bound] = INFINITY;
        ub[bound] = INFINITY;
      }

      // Call solver
      Moby::QPOASES qp;
      if (!qp.qp_activeset(H, p, lb, ub, Mc, q, A, b, z)){
            ROS_ERROR("QP failed to find feasible point");
            return false;
      }

      ROS_INFO_STREAM("QP solved successfully: " << z);

      // Copy over result
      res.torques.resize(req.torque_limits.size());
      for (unsigned int i = 0; i < z.size(); ++i) {
        res.torques[i] = z[i];
      }
      return true;
    }
  };
}

int main(int argc, char** argv) {
  ros::init(argc, argv, "balancer");
  Balancer bal;
  ros::spin();
}
<commit_msg>Finish initial version of QP<commit_after>#include <ros/ros.h>
#include <humanoid_catching/CalculateTorques.h>
#include <Moby/qpOASES.h>
#include <Ravelin/VectorNd.h>
#include <Ravelin/MatrixNd.h>
#include <Ravelin/Quatd.h>
#include <Ravelin/Opsd.h>
#include <Moby/qpOASES.h>
#include <Ravelin/LinAlgd.h>

namespace {
using namespace std;
using namespace humanoid_catching;
using namespace Ravelin;

static const double GRAVITY = 9.81;

class Balancer {
private:
    //! Node handle
    ros::NodeHandle nh;

    //! Private nh
    ros::NodeHandle pnh;

    //! Balancer Service
    ros::ServiceServer balancerService;

public:
   Balancer() :
     pnh("~") {

       balancerService = nh.advertiseService("/balancer/calculate_torques",
            &Balancer::calculateTorques, this);
	}

private:

    static Vector3d toVector(const geometry_msgs::Vector3& v3) {
        Vector3d v;
        v[0] = v3.x;
        v[1] = v3.y;
        v[2] = v3.z;
        return v;
    }

    static Vector3d toVector(const geometry_msgs::Point& p) {
        Vector3d v;
        v[0] = p.x;
        v[1] = p.y;
        v[2] = p.z;
        return v;
    }

    bool calculateTorques(humanoid_catching::CalculateTorques::Request& req,
               humanoid_catching::CalculateTorques::Response& res) {

      ROS_INFO("Calculating torques frame %s", req.header.frame_id.c_str());

      // x
      // linear velocity of body
      Vector3d x = toVector(req.body_velocity.linear);

      // w
      // angular velocity of body
      Vector3d w = toVector(req.body_velocity.angular);

      // v(t)
      // | x |
      // | w |
      VectorNd v(6);
      v.set_sub_vec(0, x);
      v.set_sub_vec(3, w);

      // R
      // Pole rotation matrix
      Matrix3d R = MatrixNd(Quatd(req.body_com.orientation.x, req.body_com.orientation.y, req.body_com.orientation.z, req.body_com.orientation.w));

      // J
      // Pole inertia matrix
      Matrix3d J = MatrixNd(VectorNd(req.body_inertia_matrix.size(), &req.body_inertia_matrix[0]));

      // JRobot
      // Robot jacobian matrix
      Matrix3d JRobot = MatrixNd(VectorNd(req.jacobian_matrix.size(), &req.jacobian_matrix[0]));

      // 3x3 working matrix
      Matrix3d temp;

      // RJR_t
      Matrix3d RJR = R.mult(J, temp).mult(Matrix3d::transpose(R), temp);

      // M
      // | Im   0 |
      // | 0 RJR_t|
      MatrixNd M(6, 6);
      M.set_zero(M.rows(), M.columns());
      M.set_sub_mat(0, 0, Matrix3d::identity() * req.body_mass);
      M.set_sub_mat(3, 3, RJR);

      // delta t
      double deltaT = req.time_delta.toSec();

      // Working vector
      Vector3d tempVector;

      // fext
      // | g           |
      // | -w x RJR_tw |
      VectorNd fExt(6);
      fExt[0] = 0;
      fExt[1] = 0;
      fExt[2] = GRAVITY;
      fExt.set_sub_vec(3, Vector3d::cross(-w, RJR.mult(w, tempVector)));

      // n_hat
      // x component of ground contact position
      Vector3d nHat;
      nHat[0] = req.ground_contact.x;
      nHat[1] = 0;
      nHat[2] = 0;

      // s_hat
      // s component of contact position
      Vector3d sHat;
      nHat[0] = 0;
      nHat[1] = req.ground_contact.y;
      nHat[2] = 0;

      // t_hat
      // z component of contact position
      Vector3d tHat;
      tHat[0] = 0;
      tHat[1] = 0;
      tHat[2] = req.ground_contact.z;

      // q_hat
      // contact normal
      Vector3d qHat = toVector(req.contact_normal);

      // p
      // contact point
      Vector3d p = toVector(req.ground_contact);

      // x_bar
      // pole COM
      Vector3d xBar = toVector(req.body_com.position);

      // r
      Vector3d r = p - xBar;

      // N
      // | n_hat     |
      // | r x n_hat |
      VectorNd N(6);
      N.set_sub_vec(0, nHat);
      N.set_sub_vec(3, r.cross(nHat, tempVector));

      // S
      // | s_hat     |
      // | r x s_hat |
      VectorNd S(6);
      S.set_sub_vec(0, sHat);
      S.set_sub_vec(3, r.cross(sHat, tempVector));

      // T
      // | t_hat     |
      // | r x t_hat |
      VectorNd T(6);
      T.set_sub_vec(0, tHat);
      T.set_sub_vec(3, r.cross(tHat, tempVector));

      // Q
      VectorNd Q(6);
      Q.set_sub_vec(0, qHat);
      Q.set_sub_vec(3, -r.cross(qHat, tempVector));

      // Result vector
      // Torques, f_n, f_s, f_t, f_robot, v_(t + tdelta)
      const int torqueIdx = 0;
      const int fNIdx = req.torque_limits.size();
      const int fSIdx = fNIdx + 1;
      const int fTIdx = fSIdx + 1;
      const int fRobotIdx = fTIdx + 1;
      const int vTDeltaIdx = fRobotIdx + 1;
      VectorNd z(req.torque_limits.size() + 1 + 1 + 1 + 1 + 6);

      // Set up minimization function
      MatrixNd H(6, z.size());
      H.set_sub_mat(0, vTDeltaIdx, M);

      VectorNd c(6);
      c.set_zero(c.rows());

      // Linear equality constraints
      MatrixNd A(6 * 3 + req.torque_limits.size(), z.size());
      VectorNd b(6 * 3 + req.torque_limits.size());

      // Sv(t + t_delta) = 0 (no tangent velocity)
      unsigned idx = 0;
      A.set_sub_mat(idx, vTDeltaIdx, S);
      b.set_sub_vec(idx, VectorNd::zero(6));
      idx += 6;

      // Tv(t + t_delta) = 0 (no tangent velocity)
      A.set_sub_mat(idx, vTDeltaIdx, T);
      b.set_sub_vec(idx, VectorNd::zero(6));
      idx += 6;

      // J_robot(transpose) * Q(transpose) * f_robot = torques
      MatrixNd JQ(req.torque_limits.size(), 1);
      MatrixNd Jt(JRobot.columns(), JRobot.rows());
      JRobot.transpose(Jt);
      MatrixNd::mult(Jt, MatrixNd(Q, eTranspose), JQ);
      A.set_sub_mat(idx, fRobotIdx, JQ);
      A.set_sub_mat(idx, torqueIdx, MatrixNd::identity(req.torque_limits.size()).negate());
      b.set_sub_vec(idx, VectorNd::zero(req.torque_limits.size()));
      idx += 6;

      // v_(t + t_delta) = v_t + M_inv (N_t * f_n + S_t * f_s + T_t * f_t + delta_t * f_ext + Q_t * delta_t * f_robot)
      // Manipulated to fit constraint form
      // -v_t - M_inv * delta_t * f_ext = M_inv * N_t * f_n + M_inv * S_t * f_s + M_inv * T_t * f_t + M_inv * Q_t * delta_t * f_robot + -v_(t + t_delta)
      LinAlgd linAlgd;
      MatrixNd MInverse = M;
      linAlgd.pseudo_invert(MInverse);

      MatrixNd MInverseN(MInverse.rows(), N.columns());
      MInverse.mult(N, MInverseN);
      A.set_sub_mat(idx, fNIdx, MInverseN);

      MatrixNd MInverseS(MInverse.rows(), S.columns());
      MInverse.mult(S, MInverseS);
      A.set_sub_mat(idx, fSIdx, MInverseS);

      MatrixNd MInverseT(MInverse.rows(), T.columns());
      MInverse.mult(T, MInverseT);
      A.set_sub_mat(idx, fTIdx,MInverseT);

      MatrixNd MInverseQ(MInverse.rows(), Q.columns());
      MInverse.mult(Q, MInverseQ);
      MInverseQ *= deltaT;
      A.set_sub_mat(idx, fRobotIdx, MInverseQ);
      A.set_sub_mat(idx, vTDeltaIdx, MatrixNd::identity(6).negate());

      VectorNd MInverseFExt(6);
      MInverseFExt.set_zero();
      MInverse.mult(fExt, MInverseFExt, deltaT);
      MInverseFExt.negate() -= v;
      b.set_sub_vec(idx, MInverseFExt);

      // Linear inequality constraints
      MatrixNd Mc(6, z.size());
      VectorNd q(6);

      // Nv(t) >= 0 (non-negative normal velocity)
      Mc.set_sub_mat(0, req.torque_limits.size() + 6 * 4, N);
      q.set_sub_vec(0, VectorNd::zero(6));

      // Solution variable constraint
      VectorNd lb(z.size());
      VectorNd ub(z.size());

      // Torque constraints
      unsigned int bound = 0;
      for (bound; bound < req.torque_limits.size(); ++bound) {
        lb[bound] = req.torque_limits[bound].minimum;
        ub[bound] = req.torque_limits[bound].maximum;
      }

      // f_n >= 0
      lb[bound] = 0;
      ub[bound] = INFINITY;
      ++bound;

      // f_s (no constraints)
      lb[bound] = INFINITY;
      ub[bound] = INFINITY;
      ++bound;

      // f_t (no constraints)
      lb[bound] = INFINITY;
      ub[bound] = INFINITY;
      ++bound;

      // f_robot >= 0
      lb[bound] = INFINITY;
      ub[bound] = INFINITY;
      ++bound;

      // v_t (no constraints)
      for (bound; bound < z.size(); ++bound) {
        lb[bound] = INFINITY;
        ub[bound] = INFINITY;
      }

      // Call solver
      Moby::QPOASES qp;
      if (!qp.qp_activeset(H, p, lb, ub, Mc, q, A, b, z)){
            ROS_ERROR("QP failed to find feasible point");
            return false;
      }

      ROS_INFO_STREAM("QP solved successfully: " << z);

      // Copy over result
      res.torques.resize(req.torque_limits.size());
      for (unsigned int i = 0; i < z.size(); ++i) {
        res.torques[i] = z[i];
      }
      return true;
    }
  };
}

int main(int argc, char** argv) {
  ros::init(argc, argv, "balancer");
  Balancer bal;
  ros::spin();
}
<|endoftext|>


<commit_before>#include "fid/base_fid.h"

namespace fid {

void BaseFid::Init()
{
  // Initialize the health properly.
  health_ = 100.0;

  // Resize the temp array (maybe others?)
  temp_.reserve(wf_.size());

  // Initialize the BaseFid for analysis
  LoadParams();
  CenterFid();
  CalcNoise();
  CalcMaxAmp();
  FindFidRange();
  InitHook();

  CalcFreq();

  // Flag the FID as bad if it's negative.
  if (freq_ < 0.0) {
    health_ = 0.0;
  }

  // Else calculate a health based on signal to noise.
  if (max_amp_ < noise_ * snr_thresh_) {
    health_ *= max_amp_ / (noise_ * snr_thresh_);
  }

  // And factor fid duration into health.
  if (f_wf_ - i_wf_ < wf_.size() * len_thresh_) {
    health_ *= (f_wf_ - i_wf_) / (wf_.size() * len_thresh_);
  }
}

// Load FID data from a formatted text file.
void BaseFid::LoadTextData(std::string filename)
{
  // open the file first
  std::ifstream in(filename);

  // shrink vectors
  wf_.resize(0);
  tm_.resize(0);

  double wf_temp;
  double tm_temp;

  while (in.good()) {
    in >> tm_temp >> wf_temp;
    tm_.push_back(tm_temp);
    wf_.push_back(wf_temp);
  }
}

// Load all the current parameters in the fid::params namespace.
void BaseFid::LoadParams()
{
  edge_width_ = params::edge_width;
  edge_ignore_ = params::edge_ignore;
  start_amplitude_ = params::start_amplitude;
  low_pass_freq_ = params::low_pass_freq;
  fft_peak_width_ = params::fft_peak_width;
  centroid_thresh_ = params::centroid_thresh;
  hyst_thresh_ = params::hyst_thresh;
  snr_thresh_ = params::snr_thresh;
  len_thresh_ = params::len_thresh;
  freq_method_ = params::freq_method;
}

void BaseFid::CenterFid()
{
  int w = edge_width_;
  double sum  = std::accumulate(wf_.begin(), wf_.begin() + w, 0.0);
  double avg = sum / w; // to pass into lambda
  mean_ = avg; // save to class

  std::for_each(wf_.begin(), wf_.end(), [avg](double& x){ x -= avg; });
}

void BaseFid::CalcNoise()
{
  // Grab a new handle to the noise window width for aesthetics.
  int i = edge_ignore_;
  int f = edge_width_ + i;

  // Find the noise level in the head and tail.
  double head = stdev(wf_.begin() + i, wf_.begin() + f);
  double tail = stdev(wf_.rbegin() + i, wf_.rbegin() + f);

  // Take the smaller of the two.
  noise_ = (tail < head) ? (tail) : (head);
}

void BaseFid::CalcMaxAmp()
{
  auto mm = std::minmax_element(wf_.begin(), wf_.end());

  if (std::abs(*mm.first) > std::abs(*mm.second)) {

    max_amp_ = std::abs(*mm.first);

  } else {

    max_amp_ = std::abs(*mm.second);
  }
}

void BaseFid::FindFidRange()
{
  // Find the starting and ending points
  double thresh = start_amplitude_ * max_amp_;
  bool checks_out = false;

  // Find the first element with magnitude larger than thresh
  auto it_1 = wf_.begin() + edge_ignore_;

  while (!checks_out) {

    // Check if the point is above threshold.
    auto it_i = std::find_if(it_1, wf_.end(),
      [thresh](double x) {
        return std::abs(x) > thresh;
    });

    // Make sure the point is not with one of the vector's end.
    if ((it_i != wf_.end()) && (it_i + 1 != wf_.end())) {

      // Check if the next point is also over threshold.
      checks_out = std::abs(*(it_i + 1)) > thresh;

      // Increase the comparison starting point.
      it_1 = it_i + 1;

      // Turn the iterator into an index
      if (checks_out) {
        i_wf_ = std::distance(wf_.begin(), it_i);
      }

    } else {

      // If we have reached the end, mark it as the last.
      i_wf_ = std::distance(wf_.begin(), wf_.end());
      break;
    }
  }

  // Find the next element with magnitude lower than thresh
  auto it_2 = std::find_if(wf_.begin() + i_wf_, wf_.end(),
      [thresh](double x) {
        return std::abs(x) < 0.8 * thresh;
  });

  checks_out = false;

  while (!checks_out) {

    // Find the range around a peak.
    auto it_i = std::find_if(it_2, wf_.end(),
      [thresh](double x) {
        return std::abs(x) > 0.8 * thresh;
    });

    auto it_f = std::find_if(it_i + 1, wf_.end(),
      [thresh](double x) {
        return std::abs(x) < 0.8 * thresh;
    });

    // Now check if the peak actually made it over threshold.
    if ((it_i != wf_.end()) && (it_f != wf_.end())) {

      auto mm = std::minmax_element(it_i, it_f);

      if ((*mm.first < -thresh) || (*mm.second > thresh)) {

        it_2 = it_f;

      } else {

        checks_out = true;
      }

      // Turn the iterator into an index
      if (checks_out) {
        f_wf_ = std::distance(wf_.begin(), it_f);
      }

    } else {

      f_wf_ = std::distance(wf_.begin(), wf_.end());
      break;
    }
  }

  // Gradients can cause a waist in the amplitude.
  // Mark the signal as bad if it didn't find signal above threshold.
  if (i_wf_ > wf_.size() * 0.95 || i_wf_ >= f_wf_) {

    health_ = 0.0;

    i_wf_ = 0;
    f_wf_ = wf_.size() * 0.01;
  }
}

// Save the interanl TGraph.
void BaseFid::SaveGraph(std::string filename, std::string title)
{
  gr_.SetTitle(title.c_str());
  gr_.Draw();
  c1_.Print(filename.c_str());
}

// Save a plot of FID waveform.
void BaseFid::SavePlot(std::string filename, std::string title)
{
  // If no title supplied give a reasonable default.
  if (title == "") {

    title = std::string("FID; time [ms]; amplitude [a.u.]");

  } else {

    // In case they didn't append x/y labels.
    title.append("; time [ms]; amplitude [a.u.]");
  }

  gr_ = TGraph(wf_.size(), &tm_[0], &wf_[0]);

  SaveGraph(filename, title);
}

// Print the time series fit from an FID.
void BaseFid::SaveTimeFit(std::string filename, std::string title)
{
  if (title == "") {

    title = std::string("Time Series Fit; time [ms]; amplitude [a.u.]");

  } else {

    // In case they didn't append x/y labels.
    title.append("; time [ms]; amplitude [a.u.]");
  }

  // Copy the current time fit graph.
  gr_ = gr_time_series_;
  SaveGraph(filename, title);
}

// Print the time series fit from an FID.
void BaseFid::SaveFreqFit(std::string filename, std::string title)
{
  if (title == "") {

    title = std::string("Frequency Series Fit; time [ms]; amplitude [a.u.]");

  } else {

    // In case they didn't append x/y labels.
    title.append("; freq [kHz]; amplitude [a.u.]");
  }

  // Copy the current time fit graph.
  gr_ = gr_freq_series_;
  SaveGraph(filename, title);
}

void BaseFid::SaveTimeRes(std::string filename, std::string title)
{
  if (title == "") {

    title = std::string("Time Series Fit Residuals; time [ms]; amplitude [a.u.]");

  } else {

    // In case they didn't append x/y labels.
    title.append("; time [ms]; amplitude [a.u.]");
  }

  // Copy the current time fit.
  gr_ = gr_time_series_;

  // Set the points
  for (uint i = 0; i < res_.size(); ++i){
    static double x, y;

    gr_.GetPoint(i, x, y);
    gr_.SetPoint(i, x, res_[i]);
  }

  SaveGraph(filename, title);
}

void BaseFid::SaveFreqRes(std::string filename, std::string title)
{
  if (title == "") {

    title = std::string("Freq Series Fit Residuals; time [ms]; amplitude [a.u.]");

  } else {

    // In case they didn't append x/y labels.
    title.append("; freq [kHz]; amplitude [a.u.]");
  }

  // Copy the current time fit.
  gr_ = gr_freq_series_;

  // Set the points
  for (uint i = 0; i < res_.size(); ++i){
    static double x, y;

    gr_.GetPoint(i, x, y);
    gr_.SetPoint(i, x, res_[i]);
  }

  SaveGraph(filename, title);
}

// Save the FID data to a text file as "<time> <amp>".
void BaseFid::SaveData(std::string filename)
{
  // open the file first
  std::ofstream out(filename);

  for (int i = 0; i < tm_.size(); ++i) {
    out << tm_[i] << " " << wf_[i] << std::endl;
  }
}

void BaseFid::DiagnosticInfo(std::ostream& out)
{
  using std::endl;

  // Save the flags, set them to defaults.
  auto flags = out.flags();
  std::ofstream testout;
  out.flags(testout.flags());

  out << std::string(80, '<') << endl << std::string(4, ' ');
  out << "Diagostic Information for Fid @ " << this << endl;
  out << std::string(80, '<') << endl;

  out << "    Fid Waveform Characteristics" << endl;
  out << "        mean:       " << mean_ << endl;
  out << "        amplitude:  " << max_amp_ << endl;
  out << "        noise:      " << noise_ << endl;
  out << "        start time: " << i_wf_;
  out << " (" << tm_[i_wf_] << " ms)" << endl;
  out << "        stop time:  " << f_wf_ - 1;
  out << " (" << tm_[f_wf_ - 1] << " ms)" << endl;
  out << "        health:     " << health_ << endl;
  out << std::string(80, '>') << endl << endl;

  // Restore set flags.
  out.flags(flags);
}

void BaseFid::DiagnosticPlot(std::string dirname, std::string filestub)
{
  boost::filesystem::path dir(dirname);
  boost::filesystem::create_directories(dir);

  SaveFreqFit(dir.string() + filestub + std::string("_freq_fit.png"));
  SaveTimeFit(dir.string() + filestub + std::string("_time_fit.png"));
  SaveFreqRes(dir.string() + filestub + std::string("_freq_res.png"));
  SaveTimeRes(dir.string() + filestub + std::string("_time_res.png"));
}

void BaseFid::DiagnosticDump(std::string dirname, std::string filestub)
{
  // Make the plots first, that will create the directory if needed.
  DiagnosticPlot(dirname, filestub);

  std::ofstream out;
  boost::filesystem::path dir(dirname);

  std::string str = dir.string() + std::string("libfid.log");
  out.open(str , std::ofstream::out | std::ofstream::app);

  DiagnosticInfo(out);
  out.close();
}

} // fid
<commit_msg>Fixes a range access problem when data is empty.<commit_after>#include "fid/base_fid.h"

namespace fid {

void BaseFid::Init()
{
  // Initialize the health properly.
  health_ = 100.0;

  // Resize the temp array (maybe others?)
  temp_.reserve(wf_.size());

  // Initialize the BaseFid for analysis
  LoadParams();
  CenterFid();
  CalcNoise();
  CalcMaxAmp();
  FindFidRange();
  InitHook();

  CalcFreq();

  // Flag the FID as bad if it's negative.
  if (freq_ < 0.0) {
    health_ = 0.0;
  }

  // Else calculate a health based on signal to noise.
  if (max_amp_ < noise_ * snr_thresh_) {
    health_ *= max_amp_ / (noise_ * snr_thresh_);
  }

  // And factor fid duration into health.
  if (f_wf_ - i_wf_ < wf_.size() * len_thresh_) {
    health_ *= (f_wf_ - i_wf_) / (wf_.size() * len_thresh_);
  }
}

// Load FID data from a formatted text file.
void BaseFid::LoadTextData(std::string filename)
{
  // open the file first
  std::ifstream in(filename);

  // shrink vectors
  wf_.resize(0);
  tm_.resize(0);

  double wf_temp;
  double tm_temp;

  while (in.good()) {
    in >> tm_temp >> wf_temp;
    tm_.push_back(tm_temp);
    wf_.push_back(wf_temp);
  }
}

// Load all the current parameters in the fid::params namespace.
void BaseFid::LoadParams()
{
  edge_width_ = params::edge_width;
  edge_ignore_ = params::edge_ignore;
  start_amplitude_ = params::start_amplitude;
  low_pass_freq_ = params::low_pass_freq;
  fft_peak_width_ = params::fft_peak_width;
  centroid_thresh_ = params::centroid_thresh;
  hyst_thresh_ = params::hyst_thresh;
  snr_thresh_ = params::snr_thresh;
  len_thresh_ = params::len_thresh;
  freq_method_ = params::freq_method;
}

void BaseFid::CenterFid()
{
  int w = edge_width_;
  double sum  = std::accumulate(wf_.begin(), wf_.begin() + w, 0.0);
  double avg = sum / w; // to pass into lambda
  mean_ = avg; // save to class

  std::for_each(wf_.begin(), wf_.end(), [avg](double& x){ x -= avg; });
}

void BaseFid::CalcNoise()
{
  // Grab a new handle to the noise window width for aesthetics.
  int i = edge_ignore_;
  int f = edge_width_ + i;

  // Find the noise level in the head and tail.
  double head = stdev(wf_.begin() + i, wf_.begin() + f);
  double tail = stdev(wf_.rbegin() + i, wf_.rbegin() + f);

  // Take the smaller of the two.
  noise_ = (tail < head) ? (tail) : (head);
}

void BaseFid::CalcMaxAmp()
{
  auto mm = std::minmax_element(wf_.begin(), wf_.end());

  if (std::abs(*mm.first) > std::abs(*mm.second)) {

    max_amp_ = std::abs(*mm.first);

  } else {

    max_amp_ = std::abs(*mm.second);
  }
}

void BaseFid::FindFidRange()
{
  // Find the starting and ending points
  double thresh = start_amplitude_ * max_amp_;
  bool checks_out = false;

  // Find the first element with magnitude larger than thresh
  auto it_1 = wf_.begin() + edge_ignore_;

  while (!checks_out) {

    // Check if the point is above threshold.
    auto it_i = std::find_if(it_1, wf_.end(),
      [thresh](double x) {
        return std::abs(x) > thresh;
    });

    // Make sure the point is not with one of the vector's end.
    if ((it_i != wf_.end()) && (it_i + 1 != wf_.end())) {

      // Check if the next point is also over threshold.
      checks_out = std::abs(*(it_i + 1)) > thresh;

      // Increase the comparison starting point.
      it_1 = it_i + 1;

      // Turn the iterator into an index
      if (checks_out) {
        i_wf_ = std::distance(wf_.begin(), it_i);
      }

    } else {

      // If we have reached the end, mark it as the last.
      i_wf_ = std::distance(wf_.begin(), wf_.end());
      break;
    }
  }

  // Find the next element with magnitude lower than thresh
  auto it_2 = std::find_if(wf_.begin() + i_wf_, wf_.end(),
      [thresh](double x) {
        return std::abs(x) < 0.8 * thresh;
  });

  if ((it_2 != wf_.end()) && (it_2 + 1 != wf_.end())) {

    checks_out = false;

  } else {

    f_wf_ = std::distance(wf_.begin(), wf_.end());
    checks_out = true;
  }

  while (!checks_out) {

    // Find the range around a peak.
    auto it_i = std::find_if(it_2, wf_.end(),
      [thresh](double x) {
        return std::abs(x) > 0.8 * thresh;
    });

    auto it_f = std::find_if(it_i + 1, wf_.end(),
      [thresh](double x) {
        return std::abs(x) < 0.8 * thresh;
    });

    // Now check if the peak actually made it over threshold.
    if ((it_i != wf_.end()) && (it_f != wf_.end())) {

      auto mm = std::minmax_element(it_i, it_f);

      if ((*mm.first < -thresh) || (*mm.second > thresh)) {

        it_2 = it_f;

      } else {

        checks_out = true;
      }

      // Turn the iterator into an index
      if (checks_out) {
        f_wf_ = std::distance(wf_.begin(), it_f);
      }

    } else {

      f_wf_ = std::distance(wf_.begin(), wf_.end());
      break;
    }
  }

  // Gradients can cause a waist in the amplitude.
  // Mark the signal as bad if it didn't find signal above threshold.
  if (i_wf_ > wf_.size() * 0.95 || i_wf_ >= f_wf_) {

    health_ = 0.0;

    i_wf_ = 0;
    f_wf_ = wf_.size() * 0.01;
  }
}

// Save the interanl TGraph.
void BaseFid::SaveGraph(std::string filename, std::string title)
{
  gr_.SetTitle(title.c_str());
  gr_.Draw();
  c1_.Print(filename.c_str());
}

// Save a plot of FID waveform.
void BaseFid::SavePlot(std::string filename, std::string title)
{
  // If no title supplied give a reasonable default.
  if (title == "") {

    title = std::string("FID; time [ms]; amplitude [a.u.]");

  } else {

    // In case they didn't append x/y labels.
    title.append("; time [ms]; amplitude [a.u.]");
  }

  gr_ = TGraph(wf_.size(), &tm_[0], &wf_[0]);

  SaveGraph(filename, title);
}

// Print the time series fit from an FID.
void BaseFid::SaveTimeFit(std::string filename, std::string title)
{
  if (title == "") {

    title = std::string("Time Series Fit; time [ms]; amplitude [a.u.]");

  } else {

    // In case they didn't append x/y labels.
    title.append("; time [ms]; amplitude [a.u.]");
  }

  // Copy the current time fit graph.
  gr_ = gr_time_series_;
  SaveGraph(filename, title);
}

// Print the time series fit from an FID.
void BaseFid::SaveFreqFit(std::string filename, std::string title)
{
  if (title == "") {

    title = std::string("Frequency Series Fit; time [ms]; amplitude [a.u.]");

  } else {

    // In case they didn't append x/y labels.
    title.append("; freq [kHz]; amplitude [a.u.]");
  }

  // Copy the current time fit graph.
  gr_ = gr_freq_series_;
  SaveGraph(filename, title);
}

void BaseFid::SaveTimeRes(std::string filename, std::string title)
{
  if (title == "") {

    title = std::string("Time Series Fit Residuals; time [ms]; amplitude [a.u.]");

  } else {

    // In case they didn't append x/y labels.
    title.append("; time [ms]; amplitude [a.u.]");
  }

  // Copy the current time fit.
  gr_ = gr_time_series_;

  // Set the points
  for (uint i = 0; i < res_.size(); ++i){
    static double x, y;

    gr_.GetPoint(i, x, y);
    gr_.SetPoint(i, x, res_[i]);
  }

  SaveGraph(filename, title);
}

void BaseFid::SaveFreqRes(std::string filename, std::string title)
{
  if (title == "") {

    title = std::string("Freq Series Fit Residuals; time [ms]; amplitude [a.u.]");

  } else {

    // In case they didn't append x/y labels.
    title.append("; freq [kHz]; amplitude [a.u.]");
  }

  // Copy the current time fit.
  gr_ = gr_freq_series_;

  // Set the points
  for (uint i = 0; i < res_.size(); ++i){
    static double x, y;

    gr_.GetPoint(i, x, y);
    gr_.SetPoint(i, x, res_[i]);
  }

  SaveGraph(filename, title);
}

// Save the FID data to a text file as "<time> <amp>".
void BaseFid::SaveData(std::string filename)
{
  // open the file first
  std::ofstream out(filename);

  for (int i = 0; i < tm_.size(); ++i) {
    out << tm_[i] << " " << wf_[i] << std::endl;
  }
}

void BaseFid::DiagnosticInfo(std::ostream& out)
{
  using std::endl;

  // Save the flags, set them to defaults.
  auto flags = out.flags();
  std::ofstream testout;
  out.flags(testout.flags());

  out << std::string(80, '<') << endl << std::string(4, ' ');
  out << "Diagostic Information for Fid @ " << this << endl;
  out << std::string(80, '<') << endl;

  out << "    Fid Waveform Characteristics" << endl;
  out << "        mean:       " << mean_ << endl;
  out << "        amplitude:  " << max_amp_ << endl;
  out << "        noise:      " << noise_ << endl;
  out << "        start time: " << i_wf_;
  out << " (" << tm_[i_wf_] << " ms)" << endl;
  out << "        stop time:  " << f_wf_ - 1;
  out << " (" << tm_[f_wf_ - 1] << " ms)" << endl;
  out << "        health:     " << health_ << endl;
  out << std::string(80, '>') << endl << endl;

  // Restore set flags.
  out.flags(flags);
}

void BaseFid::DiagnosticPlot(std::string dirname, std::string filestub)
{
  boost::filesystem::path dir(dirname);
  boost::filesystem::create_directories(dir);

  SaveFreqFit(dir.string() + filestub + std::string("_freq_fit.png"));
  SaveTimeFit(dir.string() + filestub + std::string("_time_fit.png"));
  SaveFreqRes(dir.string() + filestub + std::string("_freq_res.png"));
  SaveTimeRes(dir.string() + filestub + std::string("_time_res.png"));
}

void BaseFid::DiagnosticDump(std::string dirname, std::string filestub)
{
  // Make the plots first, that will create the directory if needed.
  DiagnosticPlot(dirname, filestub);

  std::ofstream out;
  boost::filesystem::path dir(dirname);

  std::string str = dir.string() + std::string("libfid.log");
  out.open(str , std::ofstream::out | std::ofstream::app);

  DiagnosticInfo(out);
  out.close();
}

} // fid
<|endoftext|>