<commit_before>/*
 * Copyright 2015 Milian Wolff <mail@milianw.de>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Library General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "parser.h"

#include <ThreadWeaver/ThreadWeaver>
#include <KFormat>
#include <KLocalizedString>

#include <QTextStream>
#include <QDebug>

#include "../accumulatedtracedata.h"

#include <vector>

using namespace std;

namespace {
struct ParserData final : public AccumulatedTraceData
{
    ParserData()
    {
        chartData.push_back({0, 0, 0, 0});
    }

    void handleTimeStamp(uint64_t /*newStamp*/, uint64_t oldStamp)
    {
        maxLeakedSinceLastTimeStamp = max(maxLeakedSinceLastTimeStamp, leaked);
        chartData.push_back({oldStamp, maxLeakedSinceLastTimeStamp, totalAllocations, totalAllocated});
        maxLeakedSinceLastTimeStamp = 0;
    }

    void handleAllocation()
    {
        maxLeakedSinceLastTimeStamp = max(maxLeakedSinceLastTimeStamp, leaked);
    }

    void handleDebuggee(const char* command)
    {
        debuggee = command;
    }

    string debuggee;

    ChartData chartData;
    uint64_t maxLeakedSinceLastTimeStamp = 0;
};

QString generateSummary(const ParserData& data)
{
    QString ret;
    KFormat format;
    QTextStream stream(&ret);
    const double totalTimeS = 0.001 * data.totalTime;
    stream << "<qt>"
           << i18n("debuggee: %1", QString::fromStdString(data.debuggee)) << "
"
           // xgettext:no-c-format
           << i18n("total runtime: %1s", totalTimeS) << "
"
           << i18n("bytes allocated in total (ignoring deallocations): %1 (%2/s)",
                   format.formatByteSize(data.totalAllocated, 2), format.formatByteSize(data.totalAllocated / totalTimeS)) << "
"
           << i18n("calls to allocation functions: %1 (%2/s)",
                   data.totalAllocations, quint64(data.totalAllocations / totalTimeS)) << "
"
           << i18n("peak heap memory consumption: %1", format.formatByteSize(data.peak)) << "
"
           << i18n("total memory leaked: %1", format.formatByteSize(data.leaked)) << "
";
    stream << "</qt>";
    return ret;
}

struct StringCache
{
    StringCache(const AccumulatedTraceData& data)
    {
        m_strings.resize(data.strings.size());
        transform(data.strings.begin(), data.strings.end(),
                  m_strings.begin(), [] (const string& str) { return QString::fromStdString(str); });
    }

    QString func(const InstructionPointer& ip) const
    {
        if (ip.functionIndex) {
            // TODO: support removal of template arguments
            return stringify(ip.functionIndex);
        } else {
            return static_cast<QString>(QLatin1String("0x") + QString::number(ip.instructionPointer, 16));
        }
    }

    QString file(const InstructionPointer& ip) const
    {
        if (ip.fileIndex) {
            return stringify(ip.fileIndex);
        } else {
            return {};
        }
    }

    QString module(const InstructionPointer& ip) const
    {
        return stringify(ip.moduleIndex);
    }

    QString stringify(const StringIndex index) const
    {
        if (!index || index.index > m_strings.size()) {
            return {};
        } else {
            return m_strings.at(index.index - 1);
        }
    }

    LocationData location(const InstructionPointer& ip) const
    {
        return {func(ip), file(ip), module(ip), ip.line};
    }

    vector<QString> m_strings;
};

void setParents(QVector<RowData>& children, const RowData* parent)
{
    for (auto& row: children) {
        row.parent = parent;
        setParents(row.children, &row);
    }
}

QVector<RowData> mergeAllocations(const AccumulatedTraceData& data)
{
    QVector<RowData> topRows;
    StringCache strings(data);
    // merge allocations, leave parent pointers invalid (their location may change)
    for (const auto& allocation : data.allocations) {
        auto traceIndex = allocation.traceIndex;
        auto rows = &topRows;
        while (traceIndex) {
            const auto& trace = data.findTrace(traceIndex);
            const auto& ip = data.findIp(trace.ipIndex);
            // TODO: only store the IpIndex and use that
            auto location = strings.location(ip);
            auto it = lower_bound(rows->begin(), rows->end(), location);
            if (it != rows->end() && it->location == location) {
                it->allocated += allocation.allocated;
                it->allocations += allocation.allocations;
                it->leaked += allocation.leaked;
                it->peak = max(it->peak, static_cast<quint64>(allocation.peak));
            } else {
                it = rows->insert(it, {allocation.allocations, allocation.peak, allocation.leaked, allocation.allocated,
                                        location, nullptr, {}});
            }
            traceIndex = trace.parentIndex;
            rows = &it->children;
        }
    }
    // now set the parents, the data is constant from here on
    setParents(topRows, nullptr);
    return topRows;
}
}

Parser::Parser(QObject* parent)
    : QObject(parent)
{}

Parser::~Parser() = default;

static void buildFrameGraph(const QVector<RowData>& mergedAllocations, FlameGraphData::Stack* topStack)
{
    foreach (const auto& row, mergedAllocations) {
        if (row.children.isEmpty()) {
            // leaf node found, bubble up the parent chain to build a top-down tree
            auto node = &row;
            auto stack = topStack;
            while (node) {
                auto& data = (*stack)[node->location.function];
                // always use the leaf node's cost and propagate that one up the chain
                // otherwise we'd count the cost of some nodes multiple times
                data.cost += row.allocations;
                stack = &data.children;
                node = node->parent;
            }
        } else {
            // recurse to find a leaf
            buildFrameGraph(row.children, topStack);
        }
    }
}

void Parser::parse(const QString& path)
{
    using namespace ThreadWeaver;
    stream() << make_job([=]() {
        ParserData data;
        data.read(path.toStdString());
        emit summaryAvailable(generateSummary(data));
        const auto mergedAllocations = mergeAllocations(data);
        emit bottomUpDataAvailable(mergedAllocations);
        emit chartDataAvailable(data.chartData);
        FlameGraphData::Stack stack;
        buildFrameGraph(mergedAllocations, &stack);
        emit flameGraphDataAvailable({stack});
        emit finished();
    });
}
<commit_msg>Exclude stop indices from GUI backtraces.<commit_after>/*
 * Copyright 2015 Milian Wolff <mail@milianw.de>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Library General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "parser.h"

#include <ThreadWeaver/ThreadWeaver>
#include <KFormat>
#include <KLocalizedString>

#include <QTextStream>
#include <QDebug>

#include "../accumulatedtracedata.h"

#include <vector>

using namespace std;

namespace {
struct ParserData final : public AccumulatedTraceData
{
    ParserData()
    {
        chartData.push_back({0, 0, 0, 0});
    }

    void handleTimeStamp(uint64_t /*newStamp*/, uint64_t oldStamp)
    {
        maxLeakedSinceLastTimeStamp = max(maxLeakedSinceLastTimeStamp, leaked);
        chartData.push_back({oldStamp, maxLeakedSinceLastTimeStamp, totalAllocations, totalAllocated});
        maxLeakedSinceLastTimeStamp = 0;
    }

    void handleAllocation()
    {
        maxLeakedSinceLastTimeStamp = max(maxLeakedSinceLastTimeStamp, leaked);
    }

    void handleDebuggee(const char* command)
    {
        debuggee = command;
    }

    string debuggee;

    ChartData chartData;
    uint64_t maxLeakedSinceLastTimeStamp = 0;
};

QString generateSummary(const ParserData& data)
{
    QString ret;
    KFormat format;
    QTextStream stream(&ret);
    const double totalTimeS = 0.001 * data.totalTime;
    stream << "<qt>"
           << i18n("debuggee: %1", QString::fromStdString(data.debuggee)) << "
"
           // xgettext:no-c-format
           << i18n("total runtime: %1s", totalTimeS) << "
"
           << i18n("bytes allocated in total (ignoring deallocations): %1 (%2/s)",
                   format.formatByteSize(data.totalAllocated, 2), format.formatByteSize(data.totalAllocated / totalTimeS)) << "
"
           << i18n("calls to allocation functions: %1 (%2/s)",
                   data.totalAllocations, quint64(data.totalAllocations / totalTimeS)) << "
"
           << i18n("peak heap memory consumption: %1", format.formatByteSize(data.peak)) << "
"
           << i18n("total memory leaked: %1", format.formatByteSize(data.leaked)) << "
";
    stream << "</qt>";
    return ret;
}

struct StringCache
{
    StringCache(const AccumulatedTraceData& data)
    {
        m_strings.resize(data.strings.size());
        transform(data.strings.begin(), data.strings.end(),
                  m_strings.begin(), [] (const string& str) { return QString::fromStdString(str); });
    }

    QString func(const InstructionPointer& ip) const
    {
        if (ip.functionIndex) {
            // TODO: support removal of template arguments
            return stringify(ip.functionIndex);
        } else {
            return static_cast<QString>(QLatin1String("0x") + QString::number(ip.instructionPointer, 16));
        }
    }

    QString file(const InstructionPointer& ip) const
    {
        if (ip.fileIndex) {
            return stringify(ip.fileIndex);
        } else {
            return {};
        }
    }

    QString module(const InstructionPointer& ip) const
    {
        return stringify(ip.moduleIndex);
    }

    QString stringify(const StringIndex index) const
    {
        if (!index || index.index > m_strings.size()) {
            return {};
        } else {
            return m_strings.at(index.index - 1);
        }
    }

    LocationData location(const InstructionPointer& ip) const
    {
        return {func(ip), file(ip), module(ip), ip.line};
    }

    vector<QString> m_strings;
};

void setParents(QVector<RowData>& children, const RowData* parent)
{
    for (auto& row: children) {
        row.parent = parent;
        setParents(row.children, &row);
    }
}

QVector<RowData> mergeAllocations(const AccumulatedTraceData& data)
{
    QVector<RowData> topRows;
    StringCache strings(data);
    // merge allocations, leave parent pointers invalid (their location may change)
    for (const auto& allocation : data.allocations) {
        auto traceIndex = allocation.traceIndex;
        auto rows = &topRows;
        while (traceIndex) {
            const auto& trace = data.findTrace(traceIndex);
            const auto& ip = data.findIp(trace.ipIndex);
            // TODO: only store the IpIndex and use that
            auto location = strings.location(ip);
            auto it = lower_bound(rows->begin(), rows->end(), location);
            if (it != rows->end() && it->location == location) {
                it->allocated += allocation.allocated;
                it->allocations += allocation.allocations;
                it->leaked += allocation.leaked;
                it->peak = max(it->peak, static_cast<quint64>(allocation.peak));
            } else {
                it = rows->insert(it, {allocation.allocations, allocation.peak, allocation.leaked, allocation.allocated,
                                        location, nullptr, {}});
            }
            if (data.isStopIndex(ip.functionIndex)) {
                break;
            }
            traceIndex = trace.parentIndex;
            rows = &it->children;
        }
    }
    // now set the parents, the data is constant from here on
    setParents(topRows, nullptr);
    return topRows;
}
}

Parser::Parser(QObject* parent)
    : QObject(parent)
{}

Parser::~Parser() = default;

static void buildFrameGraph(const QVector<RowData>& mergedAllocations, FlameGraphData::Stack* topStack)
{
    foreach (const auto& row, mergedAllocations) {
        if (row.children.isEmpty()) {
            // leaf node found, bubble up the parent chain to build a top-down tree
            auto node = &row;
            auto stack = topStack;
            while (node) {
                auto& data = (*stack)[node->location.function];
                // always use the leaf node's cost and propagate that one up the chain
                // otherwise we'd count the cost of some nodes multiple times
                data.cost += row.allocations;
                stack = &data.children;
                node = node->parent;
            }
        } else {
            // recurse to find a leaf
            buildFrameGraph(row.children, topStack);
        }
    }
}

void Parser::parse(const QString& path)
{
    using namespace ThreadWeaver;
    stream() << make_job([=]() {
        ParserData data;
        data.read(path.toStdString());
        emit summaryAvailable(generateSummary(data));
        const auto mergedAllocations = mergeAllocations(data);
        emit bottomUpDataAvailable(mergedAllocations);
        emit chartDataAvailable(data.chartData);
        FlameGraphData::Stack stack;
        buildFrameGraph(mergedAllocations, &stack);
        emit flameGraphDataAvailable({stack});
        emit finished();
    });
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2015 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include "kernel/declaration.h"
#include "kernel/type_checker.h"
#include "kernel/instantiate.h"
#include "library/trace.h"
#include "library/aux_recursors.h"
#include "library/user_recursors.h"
#include "library/util.h"
#include "compiler/util.h"
#include "compiler/compiler_step_visitor.h"
#include "compiler/comp_irrelevant.h"
#include "compiler/eta_expansion.h"
#include "compiler/simp_pr1_rec.h"
#include "compiler/inliner.h"
#include "compiler/elim_recursors.h"
#include "compiler/erase_irrelevant.h"

namespace lean {
class expand_aux_recursors_fn : public compiler_step_visitor {
    enum class recursor_kind { Aux, CasesOn, NotRecursor };
    /* We only expand auxiliary recursors and user-defined recursors.
       However, we don't unfold recursors of the form C.cases_on. */
    recursor_kind get_recursor_app_kind(expr const & e) const {
        if (!is_app(e))
            return recursor_kind::NotRecursor;
        expr const & fn = get_app_fn(e);
        if (!is_constant(fn))
            return recursor_kind::NotRecursor;
        name const & n = const_name(fn);
        if (is_cases_on_recursor(env(), n)) {
            return recursor_kind::CasesOn;
        } else if (::lean::is_aux_recursor(env(), n) || is_user_defined_recursor(env(), n)) {
            return recursor_kind::Aux;
        } else {
            return recursor_kind::NotRecursor;
        }
    }

    bool is_aux_recursor(expr const & e) const {
        return get_recursor_app_kind(e) == recursor_kind::Aux;
    }

    expr visit_cases_on(expr const & e) {
        /* try to reduce cases_on */
        if (auto r1 = ctx().reduce_aux_recursor(e)) {
            if (auto r2 = ctx().norm_ext(*r1)) {
                return compiler_step_visitor::visit(*r2);
            }
        }
        return compiler_step_visitor::visit_app(e);
    }

    virtual expr visit_app(expr const & e) override {
        switch (get_recursor_app_kind(e)) {
        case recursor_kind::NotRecursor: {
            expr new_e = ctx().whnf_pred(e, [&](expr const &) { return false; });
            if (is_eqp(new_e, e))
                return compiler_step_visitor::visit_app(new_e);
            else
                return compiler_step_visitor::visit(new_e);
        }
        case recursor_kind::CasesOn:
            return visit_cases_on(e);
        case recursor_kind::Aux:
            return compiler_step_visitor::visit(ctx().whnf_pred(e, [&](expr const & e) { return is_aux_recursor(e); }));
        }
        lean_unreachable();
    }

public:
    expand_aux_recursors_fn(environment const & env):compiler_step_visitor(env) {}
};

static expr expand_aux_recursors(environment const & env, expr const & e) {
    return expand_aux_recursors_fn(env)(e);
}

static name * g_tmp_prefix = nullptr;

class preprocess_rec_fn {
    environment    m_env;

    bool check(declaration const & d, expr const & v) {
        bool memoize      = true;
        bool trusted_only = false;
        type_checker tc(m_env, memoize, trusted_only);
        expr t = tc.check(v, d.get_univ_params());
        if (!tc.is_def_eq(d.get_type(), t))
            throw exception("preprocess_rec failed");
        return true;
    }

    void display(buffer<pair<name, expr>> const & procs) {
        for (auto const & p : procs) {
            tout() << ">> " << p.first << "\n" << p.second << "\n";
        }
    }

    void erase_irrelevant(buffer<pair<name, expr>> & procs) {
        for (pair<name, expr> & p : procs) {
            p.second = ::lean::erase_irrelevant(m_env, p.second);
        }
    }

public:
    preprocess_rec_fn(environment const & env):
        m_env(env) {}

    void operator()(declaration const & d, buffer<pair<name, expr>> & procs) {
        expr v = d.get_value();
        v = expand_aux_recursors(m_env, v);
        v = mark_comp_irrelevant_subterms(m_env, v);
        v = eta_expand(m_env, v);
        v = simp_pr1_rec(m_env, v);
        v = inline_simple_definitions(m_env, v);
        v = mark_comp_irrelevant_subterms(m_env, v);
        buffer<name> aux_decls;
        v = elim_recursors(m_env, v, aux_decls);

        for (name const & n : aux_decls) {
            declaration d = m_env.get(n);
            procs.emplace_back(d.get_name(), d.get_value());
        }
        procs.emplace_back(d.get_name(), v);

        erase_irrelevant(procs);

        display(procs);
        // TODO(Leo)
        check(d, procs.back().second);
    }
};

void preprocess_rec(environment const & env, declaration const & d, buffer<pair<name, expr>> & result) {
    return preprocess_rec_fn(env)(d, result);
}

void initialize_preprocess_rec() {
    g_tmp_prefix = new name(name::mk_internal_unique_name());
}

void finalize_preprocess_rec() {
    delete g_tmp_prefix;
}
}
<commit_msg>fix(compiler/preprocess_rec): do not type check after erase_irrelevant<commit_after>/*
Copyright (c) 2015 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include "kernel/declaration.h"
#include "kernel/type_checker.h"
#include "kernel/instantiate.h"
#include "library/trace.h"
#include "library/aux_recursors.h"
#include "library/user_recursors.h"
#include "library/util.h"
#include "compiler/util.h"
#include "compiler/compiler_step_visitor.h"
#include "compiler/comp_irrelevant.h"
#include "compiler/eta_expansion.h"
#include "compiler/simp_pr1_rec.h"
#include "compiler/inliner.h"
#include "compiler/elim_recursors.h"
#include "compiler/erase_irrelevant.h"

namespace lean {
class expand_aux_recursors_fn : public compiler_step_visitor {
    enum class recursor_kind { Aux, CasesOn, NotRecursor };
    /* We only expand auxiliary recursors and user-defined recursors.
       However, we don't unfold recursors of the form C.cases_on. */
    recursor_kind get_recursor_app_kind(expr const & e) const {
        if (!is_app(e))
            return recursor_kind::NotRecursor;
        expr const & fn = get_app_fn(e);
        if (!is_constant(fn))
            return recursor_kind::NotRecursor;
        name const & n = const_name(fn);
        if (is_cases_on_recursor(env(), n)) {
            return recursor_kind::CasesOn;
        } else if (::lean::is_aux_recursor(env(), n) || is_user_defined_recursor(env(), n)) {
            return recursor_kind::Aux;
        } else {
            return recursor_kind::NotRecursor;
        }
    }

    bool is_aux_recursor(expr const & e) const {
        return get_recursor_app_kind(e) == recursor_kind::Aux;
    }

    expr visit_cases_on(expr const & e) {
        /* try to reduce cases_on */
        if (auto r1 = ctx().reduce_aux_recursor(e)) {
            if (auto r2 = ctx().norm_ext(*r1)) {
                return compiler_step_visitor::visit(*r2);
            }
        }
        return compiler_step_visitor::visit_app(e);
    }

    virtual expr visit_app(expr const & e) override {
        switch (get_recursor_app_kind(e)) {
        case recursor_kind::NotRecursor: {
            expr new_e = ctx().whnf_pred(e, [&](expr const &) { return false; });
            if (is_eqp(new_e, e))
                return compiler_step_visitor::visit_app(new_e);
            else
                return compiler_step_visitor::visit(new_e);
        }
        case recursor_kind::CasesOn:
            return visit_cases_on(e);
        case recursor_kind::Aux:
            return compiler_step_visitor::visit(ctx().whnf_pred(e, [&](expr const & e) { return is_aux_recursor(e); }));
        }
        lean_unreachable();
    }

public:
    expand_aux_recursors_fn(environment const & env):compiler_step_visitor(env) {}
};

static expr expand_aux_recursors(environment const & env, expr const & e) {
    return expand_aux_recursors_fn(env)(e);
}

static name * g_tmp_prefix = nullptr;

class preprocess_rec_fn {
    environment    m_env;

    bool check(declaration const & d, expr const & v) {
        bool memoize      = true;
        bool trusted_only = false;
        type_checker tc(m_env, memoize, trusted_only);
        expr t = tc.check(v, d.get_univ_params());
        if (!tc.is_def_eq(d.get_type(), t))
            throw exception("preprocess_rec failed");
        return true;
    }

    void display(buffer<pair<name, expr>> const & procs) {
        for (auto const & p : procs) {
            tout() << ">> " << p.first << "\n" << p.second << "\n";
        }
    }

    void erase_irrelevant(buffer<pair<name, expr>> & procs) {
        for (pair<name, expr> & p : procs) {
            p.second = ::lean::erase_irrelevant(m_env, p.second);
        }
    }

public:
    preprocess_rec_fn(environment const & env):
        m_env(env) {}

    void operator()(declaration const & d, buffer<pair<name, expr>> & procs) {
        expr v = d.get_value();
        v = expand_aux_recursors(m_env, v);
        v = mark_comp_irrelevant_subterms(m_env, v);
        v = eta_expand(m_env, v);
        v = simp_pr1_rec(m_env, v);
        v = inline_simple_definitions(m_env, v);
        v = mark_comp_irrelevant_subterms(m_env, v);
        buffer<name> aux_decls;
        v = elim_recursors(m_env, v, aux_decls);

        for (name const & n : aux_decls) {
            declaration d = m_env.get(n);
            procs.emplace_back(d.get_name(), d.get_value());
        }
        procs.emplace_back(d.get_name(), v);
        check(d, procs.back().second);

        erase_irrelevant(procs);
        display(procs);
        // TODO(Leo)

    }
};

void preprocess_rec(environment const & env, declaration const & d, buffer<pair<name, expr>> & result) {
    return preprocess_rec_fn(env)(d, result);
}

void initialize_preprocess_rec() {
    g_tmp_prefix = new name(name::mk_internal_unique_name());
}

void finalize_preprocess_rec() {
    delete g_tmp_prefix;
}
}
<|endoftext|>


<commit_before>//
//  IOSOpenGLContextManager.cpp
//  MWorksCore
//
//  Created by Christopher Stawarz on 2/14/17.
//
//

#include "IOSOpenGLContextManager.hpp"

#include "OpenGLUtilities.hpp"

//
// The technique for using a CAEAGLLayer-backed UIView for displaying OpenGL ES content is taken from
// Apple's "Real-time Video Processing Using AVPlayerItemVideoOutput" example project:
//
// https://developer.apple.com/library/content/samplecode/AVBasicVideoOutput/Introduction/Intro.html
//

@interface MWKEAGLView : UIView

@property(nonatomic, readonly) EAGLContext *context;

- (instancetype)initWithFrame:(CGRect)frame context:(EAGLContext *)context;
- (mw::OpenGLContextLock)lockContext;
- (BOOL)prepareGL;
- (void)bindDrawable;
- (void)display;

@end

@implementation MWKEAGLView {
    mw::OpenGLContextLock::unique_lock::mutex_type mutex;
    GLuint framebuffer;
    GLuint renderbuffer;
}

+ (Class)layerClass {
    return [CAEAGLLayer class];
}

- (instancetype)initWithFrame:(CGRect)frame context:(EAGLContext *)context {
    self = [super initWithFrame:frame];

    if (self) {
        _context = [context retain];
        self.layer.opaque = TRUE;
    }

    return self;
}

- (mw::OpenGLContextLock)lockContext {
    return mw::OpenGLContextLock(mw::OpenGLContextLock::unique_lock(mutex));
}

- (BOOL)prepareGL {
    glGenFramebuffers(1, &framebuffer);
    mw::gl::FramebufferBinding<GL_FRAMEBUFFER> framebufferBinding(framebuffer);

    glGenRenderbuffers(1, &renderbuffer);
    mw::gl::RenderbufferBinding<GL_RENDERBUFFER> renderbufferBinding(renderbuffer);

    [self.context renderbufferStorage:GL_RENDERBUFFER fromDrawable:static_cast<CAEAGLLayer *>(self.layer)];

    GLint backingWidth, backingHeight;
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);
    glViewport(0, 0, backingWidth, backingHeight);

    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
    return (GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER));
}

- (void)bindDrawable {
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
}

- (void)display {
    mw::gl::RenderbufferBinding<GL_RENDERBUFFER> renderbufferBinding(renderbuffer);
    [self.context presentRenderbuffer:GL_RENDERBUFFER];
}

- (void)dealloc {
    [_context release];
    [super dealloc];
}

@end

@interface MWKEAGLViewController : UIViewController
@end

@implementation MWKEAGLViewController

- (BOOL)prefersStatusBarHidden {
    return YES;
}

- (BOOL)shouldAutorotate {
    return NO;
}

@end

BEGIN_NAMESPACE_MW

IOSOpenGLContextManager::~IOSOpenGLContextManager() {
    // Calling releaseContexts here causes the application to crash at exit.  Since this class is
    // used as a singleton, it doesn't matter, anyway.
    //releaseContexts();
}

int IOSOpenGLContextManager::newFullscreenContext(int screen_number, bool render_at_full_resolution) {
    @autoreleasepool {
        if (screen_number < 0 || screen_number >= getNumDisplays()) {
            throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN,
                                  (boost::format("Invalid screen number (%d)") % screen_number).str());
        }

        EAGLSharegroup *sharegroup = nil;
        if (contexts.count > 0) {
            sharegroup = static_cast<EAGLContext *>(contexts[0]).sharegroup;
        }

        EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3 sharegroup:sharegroup];
        if (!context) {
            throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN, "Cannot create OpenGL ES context");
        }

        auto screen = UIScreen.screens[screen_number];
        __block bool success = false;

        dispatch_sync(dispatch_get_main_queue(), ^{
            if (UIWindow *window = [[UIWindow alloc] initWithFrame:screen.bounds]) {
                window.screen = screen;

                if (MWKEAGLViewController *viewController = [[MWKEAGLViewController alloc] init]) {
                    window.rootViewController = viewController;

                    if (MWKEAGLView *view = [[MWKEAGLView alloc] initWithFrame:window.bounds context:context]) {
                        viewController.view = view;
                        view.contentScaleFactor = (render_at_full_resolution ? screen.scale : 1.0);
                        [EAGLContext setCurrentContext:context];

                        if ([view prepareGL]) {
                            [window makeKeyAndVisible];

                            [contexts addObject:context];
                            [views addObject:view];
                            [windows addObject:window];

                            success = true;
                        }

                        [EAGLContext setCurrentContext:nil];
                        [view release];
                    }

                    [viewController release];
                }

                [window release];
            }
        });

        [context release];

        if (!success) {
            throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN, "Cannot create fullscreen window");
        }

        return (contexts.count - 1);
    }
}

int IOSOpenGLContextManager::newMirrorContext(bool render_at_full_resolution) {
    throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN, "Mirror windows are not supported on this OS");
}

void IOSOpenGLContextManager::releaseContexts() {
    @autoreleasepool {
        dispatch_sync(dispatch_get_main_queue(), ^{
            for (UIWindow *window in windows) {
                window.hidden = YES;
            }
            [windows removeAllObjects];
            [views removeAllObjects];
        });

        [contexts removeAllObjects];
    }
}

int IOSOpenGLContextManager::getNumDisplays() const {
    // At present, we support only the main display
    return 1;
}

OpenGLContextLock IOSOpenGLContextManager::setCurrent(int context_id) {
    @autoreleasepool {
        if (auto view = static_cast<MWKEAGLView *>(getView(context_id))) {
            if ([EAGLContext setCurrentContext:view.context]) {
                auto lock = [view lockContext];
                [view bindDrawable];
                return lock;
            }
            merror(M_DISPLAY_MESSAGE_DOMAIN, "Cannot set current OpenGL ES context");
        }
        return OpenGLContextLock();
    }
}

void IOSOpenGLContextManager::clearCurrent() {
    @autoreleasepool {
        glBindFramebuffer(GL_FRAMEBUFFER, 0);  // Unbind the view's drawable object
        [EAGLContext setCurrentContext:nil];
    }
}

void IOSOpenGLContextManager::bindDefaultFramebuffer(int context_id) {
    @autoreleasepool {
        if (auto view = static_cast<MWKEAGLView *>(getView(context_id))) {
            [view bindDrawable];
        }
    }
}

void IOSOpenGLContextManager::flush(int context_id) {
    @autoreleasepool {
        if (auto view = static_cast<MWKEAGLView *>(getView(context_id))) {
            [view display];
        }
    }
}

std::vector<float> IOSOpenGLContextManager::getColorConversionLUTData(int context_id, int numGridPoints) {
    @autoreleasepool {
        std::vector<float> lutData;

        if (auto view = getView(context_id)) {
            __block UIDisplayGamut displayGamut;
            dispatch_sync(dispatch_get_main_queue(), ^{
                displayGamut = view.window.screen.traitCollection.displayGamut;
            });

            switch (displayGamut) {
                case UIDisplayGamutSRGB:
                    // No color conversion required
                    break;

                case UIDisplayGamutP3: {
                    //
                    // According to "What's New in Metal, Part 2" (WWDC 2016, Session 605), applications should
                    // always render in the sRGB colorspace, even when the target device has a P3 display.  To use
                    // colors outside of the sRGB gamut, the app needs to use a floating-point color buffer and
                    // encode the P3-only colors using component values less than 0 or greater than 1 (as in Apple's
                    // "extended sRGB" color space).  Since StimulusDisplay uses an 8 bit per channel, integer color
                    // buffer, we're always limited to sRGB.
                    //
                    // Testing suggests that this approach is correct.  If we draw an image with high color
                    // saturation and then display it both with and without a Mac-style, LUT-based conversion
                    // from sRGB to Display P3, the unconverted colors match what we see on a Mac, while the converted
                    // colors are noticeably duller.  This makes sense, because converting, say, 100% red (255, 0, 0)
                    // in sRGB to the wider gamut of Display P3 results in smaller numerical values (234, 51, 35).
                    //
                    // https://developer.apple.com/videos/play/wwdc2016/605/
                    //
                    break;
                }

                default:
                    throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN, "Unsupported display gamut");
            }

        }

        return lutData;
    }
}

boost::shared_ptr<OpenGLContextManager> OpenGLContextManager::createPlatformOpenGLContextManager() {
    return boost::make_shared<IOSOpenGLContextManager>();
}

END_NAMESPACE_MW

<commit_msg>On iOS, use UIScreen.nativeScale to get the scale factor for the display<commit_after>//
//  IOSOpenGLContextManager.cpp
//  MWorksCore
//
//  Created by Christopher Stawarz on 2/14/17.
//
//

#include "IOSOpenGLContextManager.hpp"

#include "OpenGLUtilities.hpp"

//
// The technique for using a CAEAGLLayer-backed UIView for displaying OpenGL ES content is taken from
// Apple's "Real-time Video Processing Using AVPlayerItemVideoOutput" example project:
//
// https://developer.apple.com/library/content/samplecode/AVBasicVideoOutput/Introduction/Intro.html
//

@interface MWKEAGLView : UIView

@property(nonatomic, readonly) EAGLContext *context;

- (instancetype)initWithFrame:(CGRect)frame context:(EAGLContext *)context;
- (mw::OpenGLContextLock)lockContext;
- (BOOL)prepareGL;
- (void)bindDrawable;
- (void)display;

@end

@implementation MWKEAGLView {
    mw::OpenGLContextLock::unique_lock::mutex_type mutex;
    GLuint framebuffer;
    GLuint renderbuffer;
}

+ (Class)layerClass {
    return [CAEAGLLayer class];
}

- (instancetype)initWithFrame:(CGRect)frame context:(EAGLContext *)context {
    self = [super initWithFrame:frame];

    if (self) {
        _context = [context retain];
        self.layer.opaque = TRUE;
    }

    return self;
}

- (mw::OpenGLContextLock)lockContext {
    return mw::OpenGLContextLock(mw::OpenGLContextLock::unique_lock(mutex));
}

- (BOOL)prepareGL {
    glGenFramebuffers(1, &framebuffer);
    mw::gl::FramebufferBinding<GL_FRAMEBUFFER> framebufferBinding(framebuffer);

    glGenRenderbuffers(1, &renderbuffer);
    mw::gl::RenderbufferBinding<GL_RENDERBUFFER> renderbufferBinding(renderbuffer);

    [self.context renderbufferStorage:GL_RENDERBUFFER fromDrawable:static_cast<CAEAGLLayer *>(self.layer)];

    GLint backingWidth, backingHeight;
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);
    glViewport(0, 0, backingWidth, backingHeight);

    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
    return (GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER));
}

- (void)bindDrawable {
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
}

- (void)display {
    mw::gl::RenderbufferBinding<GL_RENDERBUFFER> renderbufferBinding(renderbuffer);
    [self.context presentRenderbuffer:GL_RENDERBUFFER];
}

- (void)dealloc {
    [_context release];
    [super dealloc];
}

@end

@interface MWKEAGLViewController : UIViewController
@end

@implementation MWKEAGLViewController

- (BOOL)prefersStatusBarHidden {
    return YES;
}

- (BOOL)shouldAutorotate {
    return NO;
}

@end

BEGIN_NAMESPACE_MW

IOSOpenGLContextManager::~IOSOpenGLContextManager() {
    // Calling releaseContexts here causes the application to crash at exit.  Since this class is
    // used as a singleton, it doesn't matter, anyway.
    //releaseContexts();
}

int IOSOpenGLContextManager::newFullscreenContext(int screen_number, bool render_at_full_resolution) {
    @autoreleasepool {
        if (screen_number < 0 || screen_number >= getNumDisplays()) {
            throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN,
                                  (boost::format("Invalid screen number (%d)") % screen_number).str());
        }

        EAGLSharegroup *sharegroup = nil;
        if (contexts.count > 0) {
            sharegroup = static_cast<EAGLContext *>(contexts[0]).sharegroup;
        }

        EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3 sharegroup:sharegroup];
        if (!context) {
            throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN, "Cannot create OpenGL ES context");
        }

        auto screen = UIScreen.screens[screen_number];
        __block bool success = false;

        dispatch_sync(dispatch_get_main_queue(), ^{
            if (UIWindow *window = [[UIWindow alloc] initWithFrame:screen.bounds]) {
                window.screen = screen;

                if (MWKEAGLViewController *viewController = [[MWKEAGLViewController alloc] init]) {
                    window.rootViewController = viewController;

                    if (MWKEAGLView *view = [[MWKEAGLView alloc] initWithFrame:window.bounds context:context]) {
                        viewController.view = view;
                        view.contentScaleFactor = (render_at_full_resolution ? screen.nativeScale : 1.0);
                        [EAGLContext setCurrentContext:context];

                        if ([view prepareGL]) {
                            [window makeKeyAndVisible];

                            [contexts addObject:context];
                            [views addObject:view];
                            [windows addObject:window];

                            success = true;
                        }

                        [EAGLContext setCurrentContext:nil];
                        [view release];
                    }

                    [viewController release];
                }

                [window release];
            }
        });

        [context release];

        if (!success) {
            throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN, "Cannot create fullscreen window");
        }

        return (contexts.count - 1);
    }
}

int IOSOpenGLContextManager::newMirrorContext(bool render_at_full_resolution) {
    throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN, "Mirror windows are not supported on this OS");
}

void IOSOpenGLContextManager::releaseContexts() {
    @autoreleasepool {
        dispatch_sync(dispatch_get_main_queue(), ^{
            for (UIWindow *window in windows) {
                window.hidden = YES;
            }
            [windows removeAllObjects];
            [views removeAllObjects];
        });

        [contexts removeAllObjects];
    }
}

int IOSOpenGLContextManager::getNumDisplays() const {
    // At present, we support only the main display
    return 1;
}

OpenGLContextLock IOSOpenGLContextManager::setCurrent(int context_id) {
    @autoreleasepool {
        if (auto view = static_cast<MWKEAGLView *>(getView(context_id))) {
            if ([EAGLContext setCurrentContext:view.context]) {
                auto lock = [view lockContext];
                [view bindDrawable];
                return lock;
            }
            merror(M_DISPLAY_MESSAGE_DOMAIN, "Cannot set current OpenGL ES context");
        }
        return OpenGLContextLock();
    }
}

void IOSOpenGLContextManager::clearCurrent() {
    @autoreleasepool {
        glBindFramebuffer(GL_FRAMEBUFFER, 0);  // Unbind the view's drawable object
        [EAGLContext setCurrentContext:nil];
    }
}

void IOSOpenGLContextManager::bindDefaultFramebuffer(int context_id) {
    @autoreleasepool {
        if (auto view = static_cast<MWKEAGLView *>(getView(context_id))) {
            [view bindDrawable];
        }
    }
}

void IOSOpenGLContextManager::flush(int context_id) {
    @autoreleasepool {
        if (auto view = static_cast<MWKEAGLView *>(getView(context_id))) {
            [view display];
        }
    }
}

std::vector<float> IOSOpenGLContextManager::getColorConversionLUTData(int context_id, int numGridPoints) {
    @autoreleasepool {
        std::vector<float> lutData;

        if (auto view = getView(context_id)) {
            __block UIDisplayGamut displayGamut;
            dispatch_sync(dispatch_get_main_queue(), ^{
                displayGamut = view.window.screen.traitCollection.displayGamut;
            });

            switch (displayGamut) {
                case UIDisplayGamutSRGB:
                    // No color conversion required
                    break;

                case UIDisplayGamutP3: {
                    //
                    // According to "What's New in Metal, Part 2" (WWDC 2016, Session 605), applications should
                    // always render in the sRGB colorspace, even when the target device has a P3 display.  To use
                    // colors outside of the sRGB gamut, the app needs to use a floating-point color buffer and
                    // encode the P3-only colors using component values less than 0 or greater than 1 (as in Apple's
                    // "extended sRGB" color space).  Since StimulusDisplay uses an 8 bit per channel, integer color
                    // buffer, we're always limited to sRGB.
                    //
                    // Testing suggests that this approach is correct.  If we draw an image with high color
                    // saturation and then display it both with and without a Mac-style, LUT-based conversion
                    // from sRGB to Display P3, the unconverted colors match what we see on a Mac, while the converted
                    // colors are noticeably duller.  This makes sense, because converting, say, 100% red (255, 0, 0)
                    // in sRGB to the wider gamut of Display P3 results in smaller numerical values (234, 51, 35).
                    //
                    // https://developer.apple.com/videos/play/wwdc2016/605/
                    //
                    break;
                }

                default:
                    throw SimpleException(M_DISPLAY_MESSAGE_DOMAIN, "Unsupported display gamut");
            }

        }

        return lutData;
    }
}

boost::shared_ptr<OpenGLContextManager> OpenGLContextManager::createPlatformOpenGLContextManager() {
    return boost::make_shared<IOSOpenGLContextManager>();
}

END_NAMESPACE_MW

<|endoftext|>


<commit_before>/* packet_test.cpp                                 -*- C++ -*-
   Rémi Attab (remi.attab@gmail.com), 06 Dec 2013
   FreeBSD-style copyright and disclaimer apply

   Packet sending and timing test.
*/

#include "client.h"
#include "provider.h"
#include "test_utils.h"

#include <vector>
#include <string>
#include <cstdlib>
#include <cassert>

using namespace std;
using namespace slick;

/******************************************************************************/
/* MISC                                                                       */
/******************************************************************************/

enum { PayloadSize = 32 };

string getStats(size_t value, size_t& oldValue)
{
    string diff = fmtValue(value - oldValue);
    oldValue = value;
    return diff;
}

/******************************************************************************/
/* PROVIDER                                                                   */
/******************************************************************************/

void runProvider(Port port)
{
    size_t recv = 0, dropped = 0;

    EndpointProvider provider(port);

    provider.onNewConnection = [] (ConnectionHandle conn) {
        fprintf(stderr, "\nprv: new %d\n", conn);;
    };
    provider.onLostConnection = [] (ConnectionHandle conn) {
        fprintf(stderr, "\nprv: lost %d\n", conn);;
    };

    provider.onPayload = [&] (ConnectionHandle conn, Payload&& data) {
        recv++;
        provider.send(conn, move(data));
    };
    provider.onDroppedPayload = [&] (ConnectionHandle, Payload&&) {
        dropped++;
    };

    thread pollTh([&] { while (true) provider.poll(); });

    size_t oldRecv = 0;
    while (true) {
        slick::sleep(1000);

        string diffRecv = getStats(recv, oldRecv);
        fprintf(stderr, "\rrecv: %s", diffRecv.c_str());
    }
}

/******************************************************************************/
/* CLIENT                                                                     */
/******************************************************************************/

void runClient(vector<string> uris)
{
    size_t sent = 0, recv = 0, dropped = 0;

    EndpointClient client;

    client.onNewConnection = [] (ConnectionHandle conn) {
        fprintf(stderr, "\ncli: new %d\n", conn);;
    };
    client.onLostConnection = [] (ConnectionHandle conn) {
        fprintf(stderr, "\ncli: lost %d\n", conn);;
    };

    client.onPayload = [&] (ConnectionHandle, Payload&&) {
        recv++;
    };
    client.onDroppedPayload = [&] (ConnectionHandle, Payload&&) {
        dropped++;
    };

    for (auto& uri : uris) client.connect(uri);

    thread pollTh([&] { while (true) client.poll(); });

    Payload payload = proto::fromString(string(PayloadSize, 'a'));
    auto sendFn = [&] {
        while (true) {
            client.broadcast(payload); sent++;
        }
    };
    thread sendTh(sendFn);

    size_t oldSent = 0, oldRecv = 0;
    while (true) {
        slick::sleep(1000);

        string diffSent = getStats(sent - dropped, oldSent);
        string diffRecv = getStats(recv, oldRecv);

        fprintf(stderr, "\rsent: %s, recv: %s, ",
                diffSent.c_str(), diffRecv.c_str());
    }
}

/******************************************************************************/
/* MAIN                                                                       */
/******************************************************************************/

int main(int argc, char** argv)
{
    assert(argc >= 2);

    if (argv[1][0] == 'p') {
        Port port = 20000;
        if (argc >= 3) port = atoi(argv[2]);
        runProvider(port);
    }

    else if (argv[1][0] == 'c') {
        assert(argc >= 3);

        vector<string> uris;
        for (size_t i = 2; i < size_t(argc); ++i)
            uris.emplace_back(argv[i]);
        runClient(uris);
    }

    else assert(false);

    return 0;
}
<commit_msg>Time output for the packet test.<commit_after>/* packet_test.cpp                                 -*- C++ -*-
   Rémi Attab (remi.attab@gmail.com), 06 Dec 2013
   FreeBSD-style copyright and disclaimer apply

   Packet sending and timing test.
*/

#include "client.h"
#include "provider.h"
#include "test_utils.h"

#include <vector>
#include <string>
#include <cstdlib>
#include <cassert>

using namespace std;
using namespace slick;

/******************************************************************************/
/* MISC                                                                       */
/******************************************************************************/

enum {
    PayloadSize = 32,
    RefreshRate = 200,
};

string getStats(size_t value, size_t& oldValue)
{
    size_t diff = value - oldValue;
    diff *= 1000 / RefreshRate;

    oldValue = value;

    return fmtValue(diff);
}

/******************************************************************************/
/* PROVIDER                                                                   */
/******************************************************************************/

void runProvider(Port port)
{
    size_t recv = 0, dropped = 0;

    EndpointProvider provider(port);

    provider.onNewConnection = [] (ConnectionHandle conn) {
        fprintf(stderr, "\nprv: new %d\n", conn);;
    };
    provider.onLostConnection = [] (ConnectionHandle conn) {
        fprintf(stderr, "\nprv: lost %d\n", conn);;
    };

    provider.onPayload = [&] (ConnectionHandle conn, Payload&& data) {
        recv++;
        provider.send(conn, move(data));
    };
    provider.onDroppedPayload = [&] (ConnectionHandle, Payload&&) {
        dropped++;
    };

    thread pollTh([&] { while (true) provider.poll(); });

    double start = wall();
    size_t oldRecv = 0;

    while (true) {
        slick::sleep(RefreshRate);

        string diffRecv = getStats(recv, oldRecv);
        string elapsed = fmtElapsed(wall() - start);

        fprintf(stderr, "\r%s> recv: %s ", elapsed.c_str(), diffRecv.c_str());
    }
}

/******************************************************************************/
/* CLIENT                                                                     */
/******************************************************************************/

void runClient(vector<string> uris)
{
    size_t sent = 0, recv = 0, dropped = 0;

    EndpointClient client;

    client.onNewConnection = [] (ConnectionHandle conn) {
        fprintf(stderr, "\ncli: new %d\n", conn);;
    };
    client.onLostConnection = [] (ConnectionHandle conn) {
        fprintf(stderr, "\ncli: lost %d\n", conn);;
    };

    client.onPayload = [&] (ConnectionHandle, Payload&&) {
        recv++;
    };
    client.onDroppedPayload = [&] (ConnectionHandle, Payload&&) {
        dropped++;
    };

    for (auto& uri : uris) client.connect(uri);

    thread pollTh([&] { while (true) client.poll(); });

    Payload payload = proto::fromString(string(PayloadSize, 'a'));
    auto sendFn = [&] {
        while (true) {
            client.broadcast(payload);
            sent++;
        }
    };
    thread sendTh(sendFn);

    double start = wall();
    size_t oldSent = 0, oldRecv = 0;

    while (true) {
        slick::sleep(200);

        string diffSent = getStats(sent - dropped, oldSent);
        string diffRecv = getStats(recv, oldRecv);
        string elapsed = fmtElapsed(wall() - start);

        fprintf(stderr, "\r%s> sent: %s, recv: %s ",
                elapsed.c_str(), diffSent.c_str(), diffRecv.c_str());
    }
}

/******************************************************************************/
/* MAIN                                                                       */
/******************************************************************************/

int main(int argc, char** argv)
{
    assert(argc >= 2);

    if (argv[1][0] == 'p') {
        Port port = 20000;
        if (argc >= 3) port = atoi(argv[2]);
        runProvider(port);
    }

    else if (argv[1][0] == 'c') {
        assert(argc >= 3);

        vector<string> uris;
        for (size_t i = 2; i < size_t(argc); ++i)
            uris.emplace_back(argv[i]);
        runClient(uris);
    }

    else assert(false);

    return 0;
}
<|endoftext|>


<commit_before>/**
 * @file
 */
#pragma once

#include "numbirch/utility.hpp"
#include "numbirch/eigen/eigen.hpp"
#include "numbirch/numeric.hpp"

namespace numbirch {

template<class T, class>
Array<T,1> operator*(const Array<T,2>& A, const Array<T,1>& x) {
  assert(columns(A) == length(x));
  Array<T,1> y(make_shape(rows(A)));
  auto A1 = make_eigen(A);
  auto x1 = make_eigen(x);
  auto y1 = make_eigen(y);
  y1.noalias() = A1*x1;
  return y;
}

template<class T, class>
Array<T,2> operator*(const Array<T,2>& A, const Array<T,2>& B) {
  assert(columns(A) == rows(B));
  Array<T,2> C(make_shape(rows(A), columns(B)));
  auto A1 = make_eigen(A);
  auto B1 = make_eigen(B);
  auto C1 = make_eigen(C);
  C1.noalias() = A1*B1;
  return C;
}

template<class T, class>
Array<T,2> chol(const Array<T,2>& S) {
  assert(rows(S) == columns(S));
  Array<T,2> L(shape(S));
  auto S1 = make_eigen(S);
  auto L1 = make_eigen(L);
  auto llt = S1.llt();
  if (llt.info() == Eigen::Success) {
    L1 = llt.matrixL();
  } else {
    L.fill(T(0.0/0.0));
  }
  return L;
}

template<class T, class>
Array<T,2> cholinv(const Array<T,2>& L) {
  assert(rows(L) == columns(L));
  Array<T,2> B(shape(L));
  auto L1 = make_eigen(L).template triangularView<Eigen::Lower>();
  auto U1 = make_eigen(L).transpose().template triangularView<Eigen::Upper>();
  auto B1 = make_eigen(B);
  auto I1 = B1.Identity(rows(B), columns(B));
  B1.noalias() = U1.solve(L1.solve(I1));
  return B;
}

template<class T, class>
Array<T,1> cholsolve(const Array<T,2>& L, const Array<T,1>& y) {
  assert(rows(L) == columns(L));
  assert(columns(L) == length(y));
  Array<T,1> x(shape(y));
  auto L1 = make_eigen(L).template triangularView<Eigen::Lower>();
  auto U1 = make_eigen(L).transpose().template triangularView<Eigen::Upper>();
  auto x1 = make_eigen(x);
  auto y1 = make_eigen(y);
  x1.noalias() = U1.solve(L1.solve(y1));
  return x;
}

template<class T, class>
Array<T,2> cholsolve(const Array<T,2>& L, const Array<T,2>& C) {
  assert(rows(L) == columns(L));
  assert(columns(L) == rows(C));
  Array<T,2> B(shape(C));
  auto L1 = make_eigen(L).template triangularView<Eigen::Lower>();
  auto U1 = make_eigen(L).transpose().template triangularView<Eigen::Upper>();
  auto B1 = make_eigen(B);
  auto C1 = make_eigen(C);
  B1.noalias() = U1.solve(L1.solve(C1));
  return B;
}

template<class T, class>
Array<T,0> dot(const Array<T,1>& x, const Array<T,1>& y) {
  assert(length(x) == length(y));
  Array<T,0> z;
  auto x1 = make_eigen(x);
  auto y1 = make_eigen(y);
  z = x1.dot(y1);
  return z;
}

template<class T, class>
Array<T,0> frobenius(const Array<T,2>& x, const Array<T,2>& y) {
  Array<T,0> z;
  auto x1 = make_eigen(x);
  auto y1 = make_eigen(y);
  z = (x1.array()*y1.array()).sum();
  return z;
}

template<class T, class>
Array<T,1> inner(const Array<T,2>& A, const Array<T,1>& x) {
  assert(rows(A) == length(x));
  Array<T,1> y(make_shape(columns(A)));
  auto A1 = make_eigen(A);
  auto x1 = make_eigen(x);
  auto y1 = make_eigen(y);
  y1.noalias() = A1.transpose()*x1;
  return y;
}

template<class T, class>
Array<T,2> inner(const Array<T,2>& A, const Array<T,2>& B) {
  assert(rows(A) == rows(B));
  Array<T,2> C(make_shape(columns(A), columns(B)));
  auto A1 = make_eigen(A);
  auto B1 = make_eigen(B);
  auto C1 = make_eigen(C);
  C1.noalias() = A1.transpose()*B1;
  return C;
}

template<class T, class>
Array<T,2> inv(const Array<T,2>& A) {
  assert(rows(A) == columns(A));
  Array<T,2> B(shape(A));
  auto A1 = make_eigen(A);
  auto B1 = make_eigen(B);
  B1.noalias() = A1.inverse();
  return B;
}

template<class T, class>
Array<T,0> lcholdet(const Array<T,2>& L) {
  auto L1 = make_eigen(L);

  /* we have $S = LL^\top$; the determinant of $S$ is the square of the
   * determinant of $L$, the determinant of $L$ is the product of the
   * elements along the diagonal, as it is a triangular matrix; adjust for
   * log-determinant */
  return T(2.0)*L1.diagonal().array().log().sum();
}

template<class T, class>
Array<T,0> ldet(const Array<T,2>& A) {
  auto A1 = make_eigen(A);
  return A1.householderQr().logAbsDeterminant();
}

template<class T, class>
Array<T,2> outer(const Array<T,1>& x, const Array<T,1>& y) {
  Array<T,2> A(make_shape(length(x), length(y)));
  auto x1 = make_eigen(x);
  auto y1 = make_eigen(y);
  auto A1 = make_eigen(A);
  A1.noalias() = x1*y1.transpose();
  return A;
}

template<class T, class>
Array<T,2> outer(const Array<T,2>& A, const Array<T,2>& B) {
  assert(columns(A) == columns(B));
  Array<T,2> C(make_shape(rows(A), rows(B)));
  auto A1 = make_eigen(A);
  auto B1 = make_eigen(B);
  auto C1 = make_eigen(C);
  C1.noalias() = A1*B1.transpose();
  return C;
}

template<class T, class>
Array<T,2> phi(const Array<T,2>& A) {
  Array<T,2> L(make_shape(rows(A), columns(A)));
  auto A1 = make_eigen(A).template triangularView<Eigen::Lower>();
  auto L1 = make_eigen(L);
  L1 = A1;
  L1.diagonal() *= 0.5;
  return L;
}

template<class T, class>
Array<T,2> transpose(const Array<T,2>& A) {
  Array<T,2> B(make_shape(columns(A), rows(A)));
  auto A1 = make_eigen(A);
  auto B1 = make_eigen(B);
  B1.noalias() = A1.transpose();
  return B;
}

template<class T, class>
Array<T,2> tri(const Array<T,2>& A) {
  Array<T,2> L(make_shape(rows(A), columns(A)));
  auto A1 = make_eigen(A).template triangularView<Eigen::Lower>();
  auto L1 = make_eigen(L);
  L1 = A1;
  return L;
}

template<class T, class>
Array<T,1> triinner(const Array<T,2>& L, const Array<T,1>& x) {
  assert(rows(L) == length(x));
  Array<T,1> y(make_shape(columns(L)));
  auto U1 = make_eigen(L).transpose().template triangularView<Eigen::Upper>();
  auto x1 = make_eigen(x);
  auto y1 = make_eigen(y);
  y1.noalias() = U1*x1;
  return y;
}

template<class T, class>
Array<T,2> triinner(const Array<T,2>& L, const Array<T,2>& B) {
  assert(rows(L) == rows(B));
  Array<T,2> C(make_shape(columns(L), columns(B)));
  auto U1 = make_eigen(L).transpose().template triangularView<Eigen::Upper>();
  auto B1 = make_eigen(B);
  auto C1 = make_eigen(C);
  C1.noalias() = U1*B1;
  return C;
}

template<class T, class>
Array<T,2> triinv(const Array<T,2>& L) {
  assert(rows(L) == columns(L));
  Array<T,2> B(shape(L));
  auto L1 = make_eigen(L).template triangularView<Eigen::Lower>();
  auto B1 = make_eigen(B);
  B1.noalias() = L1.solve(B1.Identity(rows(B), columns(B)));
  return B;
}

template<class T, class>
Array<T,1> trimul(const Array<T,2>& L, const Array<T,1>& x) {
  assert(columns(L) == length(x));
  Array<T,1> y(make_shape(rows(L)));
  auto L1 = make_eigen(L).template triangularView<Eigen::Lower>();
  auto x1 = make_eigen(x);
  auto y1 = make_eigen(y);
  y1.noalias() = L1*x1;
  return y;
}

template<class T, class>
Array<T,2> trimul(const Array<T,2>& L, const Array<T,2>& B) {
  assert(columns(L) == rows(B));
  Array<T,2> C(make_shape(rows(L), columns(B)));
  auto L1 = make_eigen(L).template triangularView<Eigen::Lower>();
  auto B1 = make_eigen(B);
  auto C1 = make_eigen(C);
  C1.noalias() = L1*B1;
  return C;
}

template<class T, class>
Array<T,2> triouter(const Array<T,2>& A, const Array<T,2>& L) {
  assert(columns(A) == columns(L));
  Array<T,2> C(make_shape(rows(A), rows(L)));
  auto A1 = make_eigen(A);
  auto U1 = make_eigen(L).transpose().template triangularView<Eigen::Upper>();
  auto C1 = make_eigen(C);
  C1.noalias() = A1*U1;
  return C;
}

template<class T, class>
Array<T,1> trisolve(const Array<T,2>& L, const Array<T,1>& y) {
  assert(rows(L) == columns(L));
  assert(columns(L) == length(y));
  Array<T,1> x(shape(y));
  auto L1 = make_eigen(L).template triangularView<Eigen::Lower>();
  auto x1 = make_eigen(x);
  auto y1 = make_eigen(y);
  x1.noalias() = L1.solve(y1);
  return x;
}

template<class T, class>
Array<T,2> trisolve(const Array<T,2>& L, const Array<T,2>& C) {
  assert(rows(L) == columns(L));
  assert(columns(L) == rows(C));
  Array<T,2> B(shape(C));
  auto L1 = make_eigen(L).template triangularView<Eigen::Lower>();
  auto B1 = make_eigen(B);
  auto C1 = make_eigen(C);
  B1.noalias() = L1.solve(C1);
  return B;
}

}
<commit_msg>Replaced call to fill (now private) with scalar assign.<commit_after>/**
 * @file
 */
#pragma once

#include "numbirch/utility.hpp"
#include "numbirch/eigen/eigen.hpp"
#include "numbirch/numeric.hpp"

namespace numbirch {

template<class T, class>
Array<T,1> operator*(const Array<T,2>& A, const Array<T,1>& x) {
  assert(columns(A) == length(x));
  Array<T,1> y(make_shape(rows(A)));
  auto A1 = make_eigen(A);
  auto x1 = make_eigen(x);
  auto y1 = make_eigen(y);
  y1.noalias() = A1*x1;
  return y;
}

template<class T, class>
Array<T,2> operator*(const Array<T,2>& A, const Array<T,2>& B) {
  assert(columns(A) == rows(B));
  Array<T,2> C(make_shape(rows(A), columns(B)));
  auto A1 = make_eigen(A);
  auto B1 = make_eigen(B);
  auto C1 = make_eigen(C);
  C1.noalias() = A1*B1;
  return C;
}

template<class T, class>
Array<T,2> chol(const Array<T,2>& S) {
  assert(rows(S) == columns(S));
  Array<T,2> L(shape(S));
  auto S1 = make_eigen(S);
  auto L1 = make_eigen(L);
  auto llt = S1.llt();
  if (llt.info() == Eigen::Success) {
    L1 = llt.matrixL();
  } else {
    L = T(0.0/0.0);
  }
  return L;
}

template<class T, class>
Array<T,2> cholinv(const Array<T,2>& L) {
  assert(rows(L) == columns(L));
  Array<T,2> B(shape(L));
  auto L1 = make_eigen(L).template triangularView<Eigen::Lower>();
  auto U1 = make_eigen(L).transpose().template triangularView<Eigen::Upper>();
  auto B1 = make_eigen(B);
  auto I1 = B1.Identity(rows(B), columns(B));
  B1.noalias() = U1.solve(L1.solve(I1));
  return B;
}

template<class T, class>
Array<T,1> cholsolve(const Array<T,2>& L, const Array<T,1>& y) {
  assert(rows(L) == columns(L));
  assert(columns(L) == length(y));
  Array<T,1> x(shape(y));
  auto L1 = make_eigen(L).template triangularView<Eigen::Lower>();
  auto U1 = make_eigen(L).transpose().template triangularView<Eigen::Upper>();
  auto x1 = make_eigen(x);
  auto y1 = make_eigen(y);
  x1.noalias() = U1.solve(L1.solve(y1));
  return x;
}

template<class T, class>
Array<T,2> cholsolve(const Array<T,2>& L, const Array<T,2>& C) {
  assert(rows(L) == columns(L));
  assert(columns(L) == rows(C));
  Array<T,2> B(shape(C));
  auto L1 = make_eigen(L).template triangularView<Eigen::Lower>();
  auto U1 = make_eigen(L).transpose().template triangularView<Eigen::Upper>();
  auto B1 = make_eigen(B);
  auto C1 = make_eigen(C);
  B1.noalias() = U1.solve(L1.solve(C1));
  return B;
}

template<class T, class>
Array<T,0> dot(const Array<T,1>& x, const Array<T,1>& y) {
  assert(length(x) == length(y));
  Array<T,0> z;
  auto x1 = make_eigen(x);
  auto y1 = make_eigen(y);
  z = x1.dot(y1);
  return z;
}

template<class T, class>
Array<T,0> frobenius(const Array<T,2>& x, const Array<T,2>& y) {
  Array<T,0> z;
  auto x1 = make_eigen(x);
  auto y1 = make_eigen(y);
  z = (x1.array()*y1.array()).sum();
  return z;
}

template<class T, class>
Array<T,1> inner(const Array<T,2>& A, const Array<T,1>& x) {
  assert(rows(A) == length(x));
  Array<T,1> y(make_shape(columns(A)));
  auto A1 = make_eigen(A);
  auto x1 = make_eigen(x);
  auto y1 = make_eigen(y);
  y1.noalias() = A1.transpose()*x1;
  return y;
}

template<class T, class>
Array<T,2> inner(const Array<T,2>& A, const Array<T,2>& B) {
  assert(rows(A) == rows(B));
  Array<T,2> C(make_shape(columns(A), columns(B)));
  auto A1 = make_eigen(A);
  auto B1 = make_eigen(B);
  auto C1 = make_eigen(C);
  C1.noalias() = A1.transpose()*B1;
  return C;
}

template<class T, class>
Array<T,2> inv(const Array<T,2>& A) {
  assert(rows(A) == columns(A));
  Array<T,2> B(shape(A));
  auto A1 = make_eigen(A);
  auto B1 = make_eigen(B);
  B1.noalias() = A1.inverse();
  return B;
}

template<class T, class>
Array<T,0> lcholdet(const Array<T,2>& L) {
  auto L1 = make_eigen(L);

  /* we have $S = LL^\top$; the determinant of $S$ is the square of the
   * determinant of $L$, the determinant of $L$ is the product of the
   * elements along the diagonal, as it is a triangular matrix; adjust for
   * log-determinant */
  return T(2.0)*L1.diagonal().array().log().sum();
}

template<class T, class>
Array<T,0> ldet(const Array<T,2>& A) {
  auto A1 = make_eigen(A);
  return A1.householderQr().logAbsDeterminant();
}

template<class T, class>
Array<T,2> outer(const Array<T,1>& x, const Array<T,1>& y) {
  Array<T,2> A(make_shape(length(x), length(y)));
  auto x1 = make_eigen(x);
  auto y1 = make_eigen(y);
  auto A1 = make_eigen(A);
  A1.noalias() = x1*y1.transpose();
  return A;
}

template<class T, class>
Array<T,2> outer(const Array<T,2>& A, const Array<T,2>& B) {
  assert(columns(A) == columns(B));
  Array<T,2> C(make_shape(rows(A), rows(B)));
  auto A1 = make_eigen(A);
  auto B1 = make_eigen(B);
  auto C1 = make_eigen(C);
  C1.noalias() = A1*B1.transpose();
  return C;
}

template<class T, class>
Array<T,2> phi(const Array<T,2>& A) {
  Array<T,2> L(make_shape(rows(A), columns(A)));
  auto A1 = make_eigen(A).template triangularView<Eigen::Lower>();
  auto L1 = make_eigen(L);
  L1 = A1;
  L1.diagonal() *= 0.5;
  return L;
}

template<class T, class>
Array<T,2> transpose(const Array<T,2>& A) {
  Array<T,2> B(make_shape(columns(A), rows(A)));
  auto A1 = make_eigen(A);
  auto B1 = make_eigen(B);
  B1.noalias() = A1.transpose();
  return B;
}

template<class T, class>
Array<T,2> tri(const Array<T,2>& A) {
  Array<T,2> L(make_shape(rows(A), columns(A)));
  auto A1 = make_eigen(A).template triangularView<Eigen::Lower>();
  auto L1 = make_eigen(L);
  L1 = A1;
  return L;
}

template<class T, class>
Array<T,1> triinner(const Array<T,2>& L, const Array<T,1>& x) {
  assert(rows(L) == length(x));
  Array<T,1> y(make_shape(columns(L)));
  auto U1 = make_eigen(L).transpose().template triangularView<Eigen::Upper>();
  auto x1 = make_eigen(x);
  auto y1 = make_eigen(y);
  y1.noalias() = U1*x1;
  return y;
}

template<class T, class>
Array<T,2> triinner(const Array<T,2>& L, const Array<T,2>& B) {
  assert(rows(L) == rows(B));
  Array<T,2> C(make_shape(columns(L), columns(B)));
  auto U1 = make_eigen(L).transpose().template triangularView<Eigen::Upper>();
  auto B1 = make_eigen(B);
  auto C1 = make_eigen(C);
  C1.noalias() = U1*B1;
  return C;
}

template<class T, class>
Array<T,2> triinv(const Array<T,2>& L) {
  assert(rows(L) == columns(L));
  Array<T,2> B(shape(L));
  auto L1 = make_eigen(L).template triangularView<Eigen::Lower>();
  auto B1 = make_eigen(B);
  B1.noalias() = L1.solve(B1.Identity(rows(B), columns(B)));
  return B;
}

template<class T, class>
Array<T,1> trimul(const Array<T,2>& L, const Array<T,1>& x) {
  assert(columns(L) == length(x));
  Array<T,1> y(make_shape(rows(L)));
  auto L1 = make_eigen(L).template triangularView<Eigen::Lower>();
  auto x1 = make_eigen(x);
  auto y1 = make_eigen(y);
  y1.noalias() = L1*x1;
  return y;
}

template<class T, class>
Array<T,2> trimul(const Array<T,2>& L, const Array<T,2>& B) {
  assert(columns(L) == rows(B));
  Array<T,2> C(make_shape(rows(L), columns(B)));
  auto L1 = make_eigen(L).template triangularView<Eigen::Lower>();
  auto B1 = make_eigen(B);
  auto C1 = make_eigen(C);
  C1.noalias() = L1*B1;
  return C;
}

template<class T, class>
Array<T,2> triouter(const Array<T,2>& A, const Array<T,2>& L) {
  assert(columns(A) == columns(L));
  Array<T,2> C(make_shape(rows(A), rows(L)));
  auto A1 = make_eigen(A);
  auto U1 = make_eigen(L).transpose().template triangularView<Eigen::Upper>();
  auto C1 = make_eigen(C);
  C1.noalias() = A1*U1;
  return C;
}

template<class T, class>
Array<T,1> trisolve(const Array<T,2>& L, const Array<T,1>& y) {
  assert(rows(L) == columns(L));
  assert(columns(L) == length(y));
  Array<T,1> x(shape(y));
  auto L1 = make_eigen(L).template triangularView<Eigen::Lower>();
  auto x1 = make_eigen(x);
  auto y1 = make_eigen(y);
  x1.noalias() = L1.solve(y1);
  return x;
}

template<class T, class>
Array<T,2> trisolve(const Array<T,2>& L, const Array<T,2>& C) {
  assert(rows(L) == columns(L));
  assert(columns(L) == rows(C));
  Array<T,2> B(shape(C));
  auto L1 = make_eigen(L).template triangularView<Eigen::Lower>();
  auto B1 = make_eigen(B);
  auto C1 = make_eigen(C);
  B1.noalias() = L1.solve(C1);
  return B;
}

}
<|endoftext|>


<commit_before>#include <Matrix.hpp>
#include <catch.hpp>
#include <fstream>

SCENARIO("Matrix init", "[init]") {
	GIVEN("The number of lines and columns") {
		auto lines = 36;
		auto columns = 39;

		WHEN("Create instansce of Matrix") {
			Matrix matrix(lines, columns);
			THEN("The number of lines and columns must be preserved") {
				REQUIRE(matrix.GetNumberOfLines() == lines);
				REQUIRE(matrix.GetNumberOfColumns() == columns);
			}
		}
	}
}
SCENARIO("Matrix InitFromFile", "[fill]") {
	Matrix C(3, 1);
	C.InitFromFile("C3x1.txt");
	REQUIRE( C[0][0] == 1 );
	REQUIRE( C[1][0] == 2 );
	REQUIRE( C[2][0] == 0 );
}
SCENARIO("Matrix +", "[addition]") {
	Matrix A(3, 3);
	A.InitFromFile("A3x3.txt");
	Matrix B(3, 3);
	B.InitFromFile("B3x3.txt");
	Matrix expected = Matrix(3, 3);
	expected.InitFromFile("(A3x3)+(B3x3).txt");

	Matrix result = A + B;
	for (int i = 0; i < 3; i++){
		for (int j = 0; j < 3; j++){
			REQUIRE(result[i][j] == expected[i][j]);
		}
	}
}
SCENARIO("Matrix *", "[multiplication]") {
	Matrix A = Matrix(3, 3);
	A.InitFromFile("A3x3.txt");
	Matrix C = Matrix(3, 1);
	C.InitFromFile("C3x1.txt");
	Matrix expected = Matrix(3, 1);
	expected.InitFromFile("(A3x3)(C3x1).txt");

	Matrix result = A * C;
	for (int i = 0; i < 3; i++){
		for (int j = 0; j < 3; j++){
			REQUIRE(result[i][j] == expected[i][j]);
		}
	}
}
<commit_msg>Update init.cpp<commit_after>#include <Matrix.hpp>
#include <catch.hpp>
#include <fstream>

SCENARIO("Matrix init", "[init]") {
	GIVEN("The number of lines and columns") {
		auto lines = 36;
		auto columns = 39;

		WHEN("Create instansce of Matrix") {
			Matrix matrix(lines, columns);
			THEN("The number of lines and columns must be preserved") {
				REQUIRE(matrix.GetNumberOfLines() == lines);
				REQUIRE(matrix.GetNumberOfColumns() == columns);
			}
		}
	}
}
SCENARIO("Matrix InitFromFile", "[fill]") {
	Matrix C(3, 1);
	C.InitFromFile("C3x1.txt");
	REQUIRE( C[0][0] == 1 );
	REQUIRE( C[1][0] == 2 );
	REQUIRE( C[2][0] == 0 );
}
SCENARIO("Matrix +", "[addition]") {
	Matrix A(3, 3);
	A.InitFromFile("A3x3.txt");
	Matrix B(3, 3);
	B.InitFromFile("B3x3.txt");
	Matrix expected = Matrix(3, 3);
	expected.InitFromFile("(A3x3)+(B3x3).txt");

	Matrix result = A + B;
	for (int i = 0; i < 3; i++){
		for (int j = 0; j < 3; j++){
			REQUIRE(result[i][j] == expected[i][j]);
		}
	}
}
SCENARIO("Matrix *", "[multiplication]") {
	Matrix A = Matrix(3, 3);
	A.InitFromFile("A3x3.txt");
	Matrix C = Matrix(3, 1);
	C.InitFromFile("C3x1.txt");
	Matrix expected = Matrix(3, 1);
	expected.InitFromFile("(A3x3)(C3x1).txt");

	Matrix result = A * C;
	for (int i = 0; i < 3; i++){
		REQUIRE(result[i][0] == expected[i][0]);
	}
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2006-2017 Benjamin Kaufmann
//
// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
#include <clasp/enumerator.h>
#include <clasp/solver.h>
#include <clasp/util/multi_queue.h>
#include <clasp/clause.h>
namespace Clasp {
/////////////////////////////////////////////////////////////////////////////////////////
// Enumerator - Shared Queue / Thread Queue
/////////////////////////////////////////////////////////////////////////////////////////
class Enumerator::SharedQueue : public mt::MultiQueue<SharedLiterals*, void (*)(SharedLiterals*)> {
public:
	typedef mt::MultiQueue<SharedLiterals*, void (*)(SharedLiterals*)> BaseType;
	explicit SharedQueue(uint32 m) : BaseType(m, releaseLits) { reserve(m + 1); }
	bool pushRelaxed(SharedLiterals* clause)  { unsafePublish(clause); return true; }
	static void releaseLits(SharedLiterals* x){ x->release(); }
};
class Enumerator::ThreadQueue {
public:
	explicit ThreadQueue(SharedQueue& q) : queue_(&q) { tail_ = q.addThread(); }
	bool         pop(SharedLiterals*& out){ return queue_->tryConsume(tail_, out); }
	ThreadQueue* clone()                  { return new ThreadQueue(*queue_); }
private:
	Enumerator::SharedQueue*          queue_;
	Enumerator::SharedQueue::ThreadId tail_;
};
/////////////////////////////////////////////////////////////////////////////////////////
// EnumerationConstraint
/////////////////////////////////////////////////////////////////////////////////////////
EnumerationConstraint::EnumerationConstraint() : mini_(0), root_(0), state_(0), upMode_(0), heuristic_(0), disjoint_(false)  {
	setDisjoint(false);
}
EnumerationConstraint::~EnumerationConstraint() { }
void EnumerationConstraint::init(Solver& s, SharedMinimizeData* m, QueuePtr p) {
	mini_ = 0;
	queue_ = p;
	upMode_ = value_false;
	heuristic_ = 0;
	if (m) {
		OptParams opt = s.sharedContext()->configuration()->solver(s.id()).opt;
		mini_ = m->attach(s, opt);
		if (optimize()) {
			if   (opt.type != OptParams::type_bb) { upMode_ |= value_true; }
			else { heuristic_ |= 1; }
		}
		if (opt.hasOption(OptParams::heu_sign)) {
			for (const WeightLiteral* it = m->lits; !isSentinel(it->first); ++it) {
				s.setPref(it->first.var(), ValueSet::pref_value, falseValue(it->first));
			}
		}
		if (opt.hasOption(OptParams::heu_model)) { heuristic_ |= 2; }
	}
}
bool EnumerationConstraint::valid(Solver& s)         { return !optimize() || mini_->valid(s); }
void EnumerationConstraint::add(Constraint* c)       { if (c) { nogoods_.push_back(c); } }
bool EnumerationConstraint::integrateBound(Solver& s){ return !mini_ || mini_->integrate(s); }
bool EnumerationConstraint::optimize() const         { return mini_ && mini_->shared()->optimize(); }
void EnumerationConstraint::setDisjoint(bool x)      { disjoint_ = x; }
Constraint* EnumerationConstraint::cloneAttach(Solver& s) {
	EnumerationConstraint* c = clone();
	POTASSCO_REQUIRE(c != 0, "Cloning not supported by Enumerator");
	c->init(s, mini_ ? const_cast<SharedMinimizeData*>(mini_->shared()) : 0, queue_.get() ? queue_->clone() : 0);
	return c;
}
void EnumerationConstraint::end(Solver& s) {
	if (mini_) { mini_->relax(s, disjointPath()); }
	state_ = 0;
	setDisjoint(false);
	next_.clear();
	if (s.rootLevel() > root_) { s.popRootLevel(s.rootLevel() - root_); }
}
bool EnumerationConstraint::start(Solver& s, const LitVec& path, bool disjoint) {
	state_ = 0;
	root_  = s.rootLevel();
	setDisjoint(disjoint);
	if (s.pushRoot(path) && s.pushRoot(s.sharedContext()->stepLiteral())) {
		integrateBound(s);
		return true;
	}
	return false;
}
bool EnumerationConstraint::update(Solver& s) {
	ValueRep st = state();
	if (st == value_true) {
		if (s.restartOnModel()) { s.undoUntil(0); }
		if (optimize())         { s.strengthenConditional(); }
	}
	else if (st == value_false && !s.pushRoot(next_)) {
		if (!s.hasConflict()) { s.setStopConflict(); }
		return false;
	}
	state_ = 0;
	next_.clear();
	do {
		if (!s.hasConflict() && doUpdate(s) && integrateBound(s) && integrateNogoods(s)) {
			if (st == value_true) { modelHeuristic(s); }
			return true;
		}
	} while (st != value_free && s.hasConflict() && s.resolveConflict());
	return false;
}
bool EnumerationConstraint::integrateNogoods(Solver& s) {
	if (!queue_.get() || s.hasConflict()) { return !s.hasConflict(); }
	const uint32 f = ClauseCreator::clause_no_add | ClauseCreator::clause_no_release | ClauseCreator::clause_explicit;
	for (SharedLiterals* clause; queue_->pop(clause); ) {
		ClauseCreator::Result res = ClauseCreator::integrate(s, clause, f);
		if (res.local) { add(res.local);}
		if (!res.ok()) { return false;  }
	}
	return true;
}
void EnumerationConstraint::destroy(Solver* s, bool x) {
	if (mini_) { mini_->destroy(s, x); mini_ = 0; }
	queue_ = 0;
	Clasp::destroyDB(nogoods_, s, x);
	Constraint::destroy(s, x);
}
bool EnumerationConstraint::simplify(Solver& s, bool reinit) {
	if (mini_) { mini_->simplify(s, reinit); }
	simplifyDB(s, nogoods_, reinit);
	return false;
}

bool EnumerationConstraint::commitModel(Enumerator& ctx, Solver& s) {
	if (state() == value_true)          { return !next_.empty() && (s.satPrepro()->extendModel(s.model, next_), true); }
	if (mini_ && !mini_->handleModel(s)){ return false; }
	if (!ctx.tentative())               { doCommitModel(ctx, s); }
	next_ = s.symmetric();
	state_ |= value_true;
	return true;
}
bool EnumerationConstraint::commitUnsat(Enumerator& ctx, Solver& s) {
	next_.clear();
	state_ |= value_false;
	if (mini_) {
		mini_->handleUnsat(s, !disjointPath(), next_);
	}
	if (!ctx.tentative()) {
		doCommitUnsat(ctx, s);
	}
	return !s.hasConflict() || s.decisionLevel() != s.rootLevel();
}
void EnumerationConstraint::modelHeuristic(Solver& s) {
	const bool full = heuristic_ > 1;
	const bool heuristic = full || (heuristic_ == 1 && s.queueSize() == 0 && s.decisionLevel() == s.rootLevel());
	if (optimize() && heuristic && s.propagate()) {
		for (const WeightLiteral* w = mini_->shared()->lits; !isSentinel(w->first); ++w) {
			if (s.value(w->first.var()) == value_free) {
				s.assume(~w->first);
				if (!full || !s.propagate()) { break; }
			}
		}
	}
}
/////////////////////////////////////////////////////////////////////////////////////////
// Enumerator
/////////////////////////////////////////////////////////////////////////////////////////
void Model::reset() { std::memset(this, 0, sizeof(Model)); }
Enumerator::Enumerator() : mini_(0), queue_(0) { model_.reset(); }
Enumerator::~Enumerator()                            { delete queue_; }
void Enumerator::setDisjoint(Solver& s, bool b)const { constraintRef(s).setDisjoint(b); }
void Enumerator::setIgnoreSymmetric(bool b)          { model_.sym = static_cast<uint32>(b == false); }
void Enumerator::end(Solver& s)                const { constraintRef(s).end(s); }
void Enumerator::doReset()                           {}
void Enumerator::reset() {
	if (mini_) { mini_ = 0; }
	if (queue_){ delete queue_; queue_ = 0; }
	model_.reset();
	model_.ctx  = this;
	model_.sym  = 1;
	model_.type = uint32(modelType());
	model_.sId  = 0;
	doReset();
}
int  Enumerator::init(SharedContext& ctx, OptMode oMode, int limit)  {
	ctx.master()->setEnumerationConstraint(0);
	reset();
	if (oMode != MinimizeMode_t::ignore){ mini_ = ctx.minimize(); }
	limit      = limit >= 0 ? limit : 1 - int(exhaustive());
	if (limit != 1) { ctx.setPreserveModels(true); }
	queue_     = new SharedQueue(ctx.concurrency());
	ConPtr c   = doInit(ctx, mini_, limit);
	bool cons  = model_.consequences();
	if      (tentative())        { model_.type = Model::Sat; }
	else if (cons && optimize()) { ctx.warn("Optimization: Consequences may depend on enumeration order."); }
	c->init(*ctx.master(), mini_, new ThreadQueue(*queue_));
	ctx.master()->setEnumerationConstraint(c);
	return limit;
}
Enumerator::ConRef Enumerator::constraintRef(const Solver& s) const {
	POTASSCO_ASSERT(s.enumerationConstraint(), "Solver not attached");
	return static_cast<ConRef>(*s.enumerationConstraint());
}
Enumerator::ConPtr Enumerator::constraint(const Solver& s) const {
	return static_cast<ConPtr>(s.enumerationConstraint());
}
bool Enumerator::start(Solver& s, const LitVec& path, bool disjointPath) const {
	return constraintRef(s).start(s, path, disjointPath);
}
ValueRep Enumerator::commit(Solver& s) {
	if      (s.hasConflict() && s.decisionLevel() == s.rootLevel())         { return commitUnsat(s) ? value_free : value_false; }
	else if (s.numFreeVars() == 0 && s.queueSize() == 0 && !s.hasConflict()){ return commitModel(s) ? value_true : value_free;  }
	return value_free;
}
bool Enumerator::commitModel(Solver& s) {
	assert(s.numFreeVars() == 0 && !s.hasConflict() && s.queueSize() == 0);
	if (constraintRef(s).commitModel(*this, s)) {
		s.stats.addModel(s.decisionLevel());
		++model_.num;
		model_.sId    = s.id();
		model_.values = &s.model;
		model_.costs  = 0;
		model_.up     = 0;
		if (minimizer()) {
			costs_.resize(minimizer()->numRules());
			std::transform(minimizer()->adjust(), minimizer()->adjust()+costs_.size(), minimizer()->sum(), costs_.begin(), std::plus<wsum_t>());
			model_.costs = &costs_;
		}
		return true;
	}
	return false;
}
bool Enumerator::commitSymmetric(Solver& s){ return model_.sym && !optimize() && commitModel(s); }
bool Enumerator::commitUnsat(Solver& s)    { return constraintRef(s).commitUnsat(*this, s); }
bool Enumerator::commitClause(const LitVec& clause)  const {
	return queue_ && queue_->pushRelaxed(SharedLiterals::newShareable(clause, Constraint_t::Other));
}
bool Enumerator::commitComplete() {
	if (enumerated()) {
		if (tentative()) {
			mini_->markOptimal();
			model_.opt = 1;
			model_.num = 0;
			model_.type= uint32(modelType());
			return false;
		}
		else if (model_.consequences() || (!model_.opt && optimize())) {
			model_.opt = uint32(optimize());
			model_.def = uint32(model_.consequences());
			model_.num = 1;
		}
	}
	return true;
}
bool Enumerator::update(Solver& s) const {
	return constraintRef(s).update(s);
}
bool Enumerator::supportsSplitting(const SharedContext& ctx) const {
	if (!optimize()) { return true; }
	const Configuration* config = ctx.configuration();
	bool ok = true;
	for (uint32 i = 0; i != ctx.concurrency() && ok; ++i) {
		if      (ctx.hasSolver(i) && constraint(*ctx.solver(i))){ ok = constraint(*ctx.solver(i))->minimizer()->supportsSplitting(); }
		else if (config && i < config->numSolver())             { ok = config->solver(i).opt.supportsSplitting(); }
	}
	return ok;
}
int Enumerator::unsatType() const {
	return !optimize() ? unsat_stop : unsat_cont;
}
Model& Enumerator::model() {
	return model_;
}
/////////////////////////////////////////////////////////////////////////////////////////
// EnumOptions
/////////////////////////////////////////////////////////////////////////////////////////
Enumerator* EnumOptions::createEnumerator(const EnumOptions& opts) {
	if      (opts.models())      { return createModelEnumerator(opts);}
	else if (opts.consequences()){ return createConsEnumerator(opts); }
	else                         { return nullEnumerator(); }
}
Enumerator* EnumOptions::nullEnumerator() {
	struct NullEnum : Enumerator {
		ConPtr doInit(SharedContext&, SharedMinimizeData*, int) {
			struct Constraint : public EnumerationConstraint {
				Constraint() : EnumerationConstraint() {}
				ConPtr      clone()          { return new Constraint(); }
				bool        doUpdate(Solver&){ return true; }
			};
			return new Constraint();
		}
	};
	return new NullEnum;
}

const char* modelType(const Model& m) {
	switch (m.type) {
		case Model::Sat     : return "Model";
		case Model::Brave   : return "Brave";
		case Model::Cautious: return "Cautious";
		case Model::User    : return "User";
		default: return 0;
	}
}

}
<commit_msg>Integrate nogoods on Enumerator::start().<commit_after>//
// Copyright (c) 2006-2017 Benjamin Kaufmann
//
// This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
#include <clasp/enumerator.h>
#include <clasp/solver.h>
#include <clasp/util/multi_queue.h>
#include <clasp/clause.h>
namespace Clasp {
/////////////////////////////////////////////////////////////////////////////////////////
// Enumerator - Shared Queue / Thread Queue
/////////////////////////////////////////////////////////////////////////////////////////
class Enumerator::SharedQueue : public mt::MultiQueue<SharedLiterals*, void (*)(SharedLiterals*)> {
public:
	typedef mt::MultiQueue<SharedLiterals*, void (*)(SharedLiterals*)> BaseType;
	explicit SharedQueue(uint32 m) : BaseType(m, releaseLits) { reserve(m + 1); }
	bool pushRelaxed(SharedLiterals* clause)  { unsafePublish(clause); return true; }
	static void releaseLits(SharedLiterals* x){ x->release(); }
};
class Enumerator::ThreadQueue {
public:
	explicit ThreadQueue(SharedQueue& q) : queue_(&q) { tail_ = q.addThread(); }
	bool         pop(SharedLiterals*& out){ return queue_->tryConsume(tail_, out); }
	ThreadQueue* clone()                  { return new ThreadQueue(*queue_); }
private:
	Enumerator::SharedQueue*          queue_;
	Enumerator::SharedQueue::ThreadId tail_;
};
/////////////////////////////////////////////////////////////////////////////////////////
// EnumerationConstraint
/////////////////////////////////////////////////////////////////////////////////////////
EnumerationConstraint::EnumerationConstraint() : mini_(0), root_(0), state_(0), upMode_(0), heuristic_(0), disjoint_(false)  {
	setDisjoint(false);
}
EnumerationConstraint::~EnumerationConstraint() { }
void EnumerationConstraint::init(Solver& s, SharedMinimizeData* m, QueuePtr p) {
	mini_ = 0;
	queue_ = p;
	upMode_ = value_false;
	heuristic_ = 0;
	if (m) {
		OptParams opt = s.sharedContext()->configuration()->solver(s.id()).opt;
		mini_ = m->attach(s, opt);
		if (optimize()) {
			if   (opt.type != OptParams::type_bb) { upMode_ |= value_true; }
			else { heuristic_ |= 1; }
		}
		if (opt.hasOption(OptParams::heu_sign)) {
			for (const WeightLiteral* it = m->lits; !isSentinel(it->first); ++it) {
				s.setPref(it->first.var(), ValueSet::pref_value, falseValue(it->first));
			}
		}
		if (opt.hasOption(OptParams::heu_model)) { heuristic_ |= 2; }
	}
}
bool EnumerationConstraint::valid(Solver& s)         { return !optimize() || mini_->valid(s); }
void EnumerationConstraint::add(Constraint* c)       { if (c) { nogoods_.push_back(c); } }
bool EnumerationConstraint::integrateBound(Solver& s){ return !mini_ || mini_->integrate(s); }
bool EnumerationConstraint::optimize() const         { return mini_ && mini_->shared()->optimize(); }
void EnumerationConstraint::setDisjoint(bool x)      { disjoint_ = x; }
Constraint* EnumerationConstraint::cloneAttach(Solver& s) {
	EnumerationConstraint* c = clone();
	POTASSCO_REQUIRE(c != 0, "Cloning not supported by Enumerator");
	c->init(s, mini_ ? const_cast<SharedMinimizeData*>(mini_->shared()) : 0, queue_.get() ? queue_->clone() : 0);
	return c;
}
void EnumerationConstraint::end(Solver& s) {
	if (mini_) { mini_->relax(s, disjointPath()); }
	state_ = 0;
	setDisjoint(false);
	next_.clear();
	if (s.rootLevel() > root_) { s.popRootLevel(s.rootLevel() - root_); }
}
bool EnumerationConstraint::start(Solver& s, const LitVec& path, bool disjoint) {
	state_ = 0;
	root_  = s.rootLevel();
	setDisjoint(disjoint);
	if (s.pushRoot(path) && s.pushRoot(s.sharedContext()->stepLiteral())) {
		integrateBound(s);
		integrateNogoods(s);
		return true;
	}
	return false;
}
bool EnumerationConstraint::update(Solver& s) {
	ValueRep st = state();
	if (st == value_true) {
		if (s.restartOnModel()) { s.undoUntil(0); }
		if (optimize())         { s.strengthenConditional(); }
	}
	else if (st == value_false && !s.pushRoot(next_)) {
		if (!s.hasConflict()) { s.setStopConflict(); }
		return false;
	}
	state_ = 0;
	next_.clear();
	do {
		if (!s.hasConflict() && doUpdate(s) && integrateBound(s) && integrateNogoods(s)) {
			if (st == value_true) { modelHeuristic(s); }
			return true;
		}
	} while (st != value_free && s.hasConflict() && s.resolveConflict());
	return false;
}
bool EnumerationConstraint::integrateNogoods(Solver& s) {
	if (!queue_.get() || s.hasConflict()) { return !s.hasConflict(); }
	const uint32 f = ClauseCreator::clause_no_add | ClauseCreator::clause_no_release | ClauseCreator::clause_explicit;
	for (SharedLiterals* clause; queue_->pop(clause); ) {
		ClauseCreator::Result res = ClauseCreator::integrate(s, clause, f);
		if (res.local) { add(res.local);}
		if (!res.ok()) { return false;  }
	}
	return true;
}
void EnumerationConstraint::destroy(Solver* s, bool x) {
	if (mini_) { mini_->destroy(s, x); mini_ = 0; }
	queue_ = 0;
	Clasp::destroyDB(nogoods_, s, x);
	Constraint::destroy(s, x);
}
bool EnumerationConstraint::simplify(Solver& s, bool reinit) {
	if (mini_) { mini_->simplify(s, reinit); }
	simplifyDB(s, nogoods_, reinit);
	return false;
}

bool EnumerationConstraint::commitModel(Enumerator& ctx, Solver& s) {
	if (state() == value_true)          { return !next_.empty() && (s.satPrepro()->extendModel(s.model, next_), true); }
	if (mini_ && !mini_->handleModel(s)){ return false; }
	if (!ctx.tentative())               { doCommitModel(ctx, s); }
	next_ = s.symmetric();
	state_ |= value_true;
	return true;
}
bool EnumerationConstraint::commitUnsat(Enumerator& ctx, Solver& s) {
	next_.clear();
	state_ |= value_false;
	if (mini_) {
		mini_->handleUnsat(s, !disjointPath(), next_);
	}
	if (!ctx.tentative()) {
		doCommitUnsat(ctx, s);
	}
	return !s.hasConflict() || s.decisionLevel() != s.rootLevel();
}
void EnumerationConstraint::modelHeuristic(Solver& s) {
	const bool full = heuristic_ > 1;
	const bool heuristic = full || (heuristic_ == 1 && s.queueSize() == 0 && s.decisionLevel() == s.rootLevel());
	if (optimize() && heuristic && s.propagate()) {
		for (const WeightLiteral* w = mini_->shared()->lits; !isSentinel(w->first); ++w) {
			if (s.value(w->first.var()) == value_free) {
				s.assume(~w->first);
				if (!full || !s.propagate()) { break; }
			}
		}
	}
}
/////////////////////////////////////////////////////////////////////////////////////////
// Enumerator
/////////////////////////////////////////////////////////////////////////////////////////
void Model::reset() { std::memset(this, 0, sizeof(Model)); }
Enumerator::Enumerator() : mini_(0), queue_(0) { model_.reset(); }
Enumerator::~Enumerator()                            { delete queue_; }
void Enumerator::setDisjoint(Solver& s, bool b)const { constraintRef(s).setDisjoint(b); }
void Enumerator::setIgnoreSymmetric(bool b)          { model_.sym = static_cast<uint32>(b == false); }
void Enumerator::end(Solver& s)                const { constraintRef(s).end(s); }
void Enumerator::doReset()                           {}
void Enumerator::reset() {
	if (mini_) { mini_ = 0; }
	if (queue_){ delete queue_; queue_ = 0; }
	model_.reset();
	model_.ctx  = this;
	model_.sym  = 1;
	model_.type = uint32(modelType());
	model_.sId  = 0;
	doReset();
}
int  Enumerator::init(SharedContext& ctx, OptMode oMode, int limit)  {
	ctx.master()->setEnumerationConstraint(0);
	reset();
	if (oMode != MinimizeMode_t::ignore){ mini_ = ctx.minimize(); }
	limit      = limit >= 0 ? limit : 1 - int(exhaustive());
	if (limit != 1) { ctx.setPreserveModels(true); }
	queue_     = new SharedQueue(ctx.concurrency());
	ConPtr c   = doInit(ctx, mini_, limit);
	bool cons  = model_.consequences();
	if      (tentative())        { model_.type = Model::Sat; }
	else if (cons && optimize()) { ctx.warn("Optimization: Consequences may depend on enumeration order."); }
	c->init(*ctx.master(), mini_, new ThreadQueue(*queue_));
	ctx.master()->setEnumerationConstraint(c);
	return limit;
}
Enumerator::ConRef Enumerator::constraintRef(const Solver& s) const {
	POTASSCO_ASSERT(s.enumerationConstraint(), "Solver not attached");
	return static_cast<ConRef>(*s.enumerationConstraint());
}
Enumerator::ConPtr Enumerator::constraint(const Solver& s) const {
	return static_cast<ConPtr>(s.enumerationConstraint());
}
bool Enumerator::start(Solver& s, const LitVec& path, bool disjointPath) const {
	return constraintRef(s).start(s, path, disjointPath);
}
ValueRep Enumerator::commit(Solver& s) {
	if      (s.hasConflict() && s.decisionLevel() == s.rootLevel())         { return commitUnsat(s) ? value_free : value_false; }
	else if (s.numFreeVars() == 0 && s.queueSize() == 0 && !s.hasConflict()){ return commitModel(s) ? value_true : value_free;  }
	return value_free;
}
bool Enumerator::commitModel(Solver& s) {
	assert(s.numFreeVars() == 0 && !s.hasConflict() && s.queueSize() == 0);
	if (constraintRef(s).commitModel(*this, s)) {
		s.stats.addModel(s.decisionLevel());
		++model_.num;
		model_.sId    = s.id();
		model_.values = &s.model;
		model_.costs  = 0;
		model_.up     = 0;
		if (minimizer()) {
			costs_.resize(minimizer()->numRules());
			std::transform(minimizer()->adjust(), minimizer()->adjust()+costs_.size(), minimizer()->sum(), costs_.begin(), std::plus<wsum_t>());
			model_.costs = &costs_;
		}
		return true;
	}
	return false;
}
bool Enumerator::commitSymmetric(Solver& s){ return model_.sym && !optimize() && commitModel(s); }
bool Enumerator::commitUnsat(Solver& s)    { return constraintRef(s).commitUnsat(*this, s); }
bool Enumerator::commitClause(const LitVec& clause)  const {
	return queue_ && queue_->pushRelaxed(SharedLiterals::newShareable(clause, Constraint_t::Other));
}
bool Enumerator::commitComplete() {
	if (enumerated()) {
		if (tentative()) {
			mini_->markOptimal();
			model_.opt = 1;
			model_.num = 0;
			model_.type= uint32(modelType());
			return false;
		}
		else if (model_.consequences() || (!model_.opt && optimize())) {
			model_.opt = uint32(optimize());
			model_.def = uint32(model_.consequences());
			model_.num = 1;
		}
	}
	return true;
}
bool Enumerator::update(Solver& s) const {
	return constraintRef(s).update(s);
}
bool Enumerator::supportsSplitting(const SharedContext& ctx) const {
	if (!optimize()) { return true; }
	const Configuration* config = ctx.configuration();
	bool ok = true;
	for (uint32 i = 0; i != ctx.concurrency() && ok; ++i) {
		if      (ctx.hasSolver(i) && constraint(*ctx.solver(i))){ ok = constraint(*ctx.solver(i))->minimizer()->supportsSplitting(); }
		else if (config && i < config->numSolver())             { ok = config->solver(i).opt.supportsSplitting(); }
	}
	return ok;
}
int Enumerator::unsatType() const {
	return !optimize() ? unsat_stop : unsat_cont;
}
Model& Enumerator::model() {
	return model_;
}
/////////////////////////////////////////////////////////////////////////////////////////
// EnumOptions
/////////////////////////////////////////////////////////////////////////////////////////
Enumerator* EnumOptions::createEnumerator(const EnumOptions& opts) {
	if      (opts.models())      { return createModelEnumerator(opts);}
	else if (opts.consequences()){ return createConsEnumerator(opts); }
	else                         { return nullEnumerator(); }
}
Enumerator* EnumOptions::nullEnumerator() {
	struct NullEnum : Enumerator {
		ConPtr doInit(SharedContext&, SharedMinimizeData*, int) {
			struct Constraint : public EnumerationConstraint {
				Constraint() : EnumerationConstraint() {}
				ConPtr      clone()          { return new Constraint(); }
				bool        doUpdate(Solver&){ return true; }
			};
			return new Constraint();
		}
	};
	return new NullEnum;
}

const char* modelType(const Model& m) {
	switch (m.type) {
		case Model::Sat     : return "Model";
		case Model::Brave   : return "Brave";
		case Model::Cautious: return "Cautious";
		case Model::User    : return "User";
		default: return 0;
	}
}

}
<|endoftext|>


<commit_before>#include <stack.cpp>
#include <catch.hpp>
#include <iostream>
//using namespace std;

SCENARIO("count", "[count]"){
  stack<int> s;
  s.push(1);
  REQUIRE(s.count()==1);
}

SCENARIO("push", "[push]"){
  stack<int> s;
  s.push(1);
  REQUIRE(s.count()==1);
  REQUIRE(s.top()==1);
}

SCENARIO("top", "[top]"){
  stack<int> s;
  s.push(1);
  REQUIRE(s.count()==1);
  REQUIRE(s.top()==1);
}

SCENARIO("pop", "[pop]"){
  stack<int> s;
  s.push(1);
  s.push(2);
  s.pop();
  REQUIRE(s.count()==1);
  REQUIRE(s.top()==1);
}

SCENARIO("prisv", "[prisv]"){
  stack<int> s;
  s.push(1);
  stack<int> s2;
  s2=s;
  REQUIRE(s.count()==1);
  REQUIRE(s.top()==1);
}
SCENARIO("copy", "[copy]"){
  stack<int> s;
  s.push(1);
  stack <int> a = s;
  REQUIRE(a.count()==1);
  REQUIRE(a.top()==1);
}
SCENARIO("test", "[test]"){
  stack<int> s;
  REQUIRE(s.count()==0);
}
SCENARIO("empty", "[empty]"){
  stack<int> s;
  REQUIRE(s.empty()==true);
}
<commit_msg>Delete init.cpp<commit_after><|endoftext|>


<commit_before><commit_msg>Fix for param array support in effects for GL<commit_after><|endoftext|>


<commit_before>#define _POSIX_SOURCE

#include "condor_common.h"
#include "condor_debug.h"
#include "directory.h"

static char *_FileName_ = __FILE__;     /* Used by EXCEPT (see except.h)     */

Directory::Directory( const char *name )
{
	dirp = opendir( name );
	if( dirp == NULL ) {
		EXCEPT( "Can't open directory \"%s\"", name );
	}
}

Directory::~Directory()
{
	(void)closedir( dirp );
}

void
Directory::Rewind()
{
	rewinddir( dirp );
}

char *
Directory::Next()
{
	struct dirent *dirent;

	while( dirent = readdir(dirp) ) {
		if( strcmp(".",dirent->d_name) == MATCH ) {
			continue;
		}
		if( strcmp("..",dirent->d_name) == MATCH ) {
			continue;
		}
		return dirent->d_name;
	}
	return NULL;
}
<commit_msg>Included condor_constants.h for definition of the MATCH constant<commit_after>#define _POSIX_SOURCE

#include "condor_common.h"
#include "condor_constants.h"
#include "condor_debug.h"
#include "directory.h"

static char *_FileName_ = __FILE__;     /* Used by EXCEPT (see except.h)     */

Directory::Directory( const char *name )
{
	dirp = opendir( name );
	if( dirp == NULL ) {
		EXCEPT( "Can't open directory \"%s\"", name );
	}
}

Directory::~Directory()
{
	(void)closedir( dirp );
}

void
Directory::Rewind()
{
	rewinddir( dirp );
}

char *
Directory::Next()
{
	struct dirent *dirent;

	while( dirent = readdir(dirp) ) {
		if( strcmp(".",dirent->d_name) == MATCH ) {
			continue;
		}
		if( strcmp("..",dirent->d_name) == MATCH ) {
			continue;
		}
		return dirent->d_name;
	}
	return NULL;
}
<|endoftext|>