<commit_before>#include "canwrite.h"
#include "log.h"

QUEUE_DEFINE(CanMessage);

void checkWritePermission(CanSignal* signal, bool* send) {
    if(!signal->writable) {
        *send = false;
    }
}

uint64_t booleanWriter(CanSignal* signal, CanSignal* signals,
        int signalCount, cJSON* value, bool* send) {
    return booleanWriter(signal, signals, signalCount, value, send, 0);
}

uint64_t booleanWriter(CanSignal* signal, CanSignal* signals,
        int signalCount, cJSON* value, bool* send, uint64_t data) {
    checkWritePermission(signal, send);
    int intValue = 0;
    if(value->type == cJSON_False) {
        intValue = 0;
    } else if(value->type == cJSON_True) {
        intValue = 1;
    }
    return encodeCanSignal(signal, intValue, data);
}

uint64_t numberWriter(CanSignal* signal, CanSignal* signals,
        int signalCount, cJSON* value, bool* send) {
    return numberWriter(signal, signals, signalCount, value, send, 0);
}

uint64_t numberWriter(CanSignal* signal, CanSignal* signals,
        int signalCount, cJSON* value, bool* send, uint64_t data) {
    checkWritePermission(signal, send);
    return encodeCanSignal(signal, value->valuedouble, data);
}

uint64_t stateWriter(CanSignal* signal, CanSignal* signals,
        int signalCount, const char* value, bool* send, uint64_t data) {
    if(value == NULL) {
        debug("Can't write state of NULL -- not sending\r\n");
    } else {
        CanSignalState* signalState = lookupSignalState(value, signal, signals,
                signalCount);
        if(signalState != NULL) {
            checkWritePermission(signal, send);
            return encodeCanSignal(signal, signalState->value, data);
        } else {
            debug("Couldn't find a valid signal state for \"%s\"", value);
        }
    }
    *send = false;
    return 0;
}

uint64_t stateWriter(CanSignal* signal, CanSignal* signals,
        int signalCount, const char* value, bool* send) {
    return stateWriter(signal, signals, signalCount, value, send, 0);
}

uint64_t stateWriter(CanSignal* signal, CanSignal* signals,
        int signalCount, cJSON* value, bool* send, uint64_t data) {
    return stateWriter(signal, signals, signalCount, value->valuestring, send,
            data);
}

uint64_t stateWriter(CanSignal* signal, CanSignal* signals,
        int signalCount, cJSON* value, bool* send) {
    return stateWriter(signal, signals, signalCount, value, send, 0);
}

uint64_t encodeCanSignal(CanSignal* signal, float value) {
    return encodeCanSignal(signal, value, 0);
}

uint64_t encodeCanSignal(CanSignal* signal, float value, uint64_t data) {
    float rawValue = (value - signal->offset) / signal->factor;
    if(rawValue > 0) {
        // round up to avoid losing precision when we cast to an int
        rawValue += 0.5;
    }
    setBitField(&data, rawValue, signal->bitPosition, signal->bitSize);
    return data;
}

bool sendCanSignal(CanSignal* signal, uint64_t data, bool* send) {
    if(send) {
        CanMessage message = {signal->messageId, data};
        QUEUE_PUSH(CanMessage, &signal->bus->sendQueue, message);
        return true;
    }
    debug("Not sending requested message %x\r\n", signal->messageId);
    return false;
}

bool sendCanSignal(CanSignal* signal, cJSON* value, CanSignal* signals,
        int signalCount) {
    uint64_t (*writer)(CanSignal*, CanSignal*, int, cJSON*, bool*)
        = signal->writeHandler;
    return sendCanSignal(signal, value, writer, signals, signalCount);
}

bool sendCanSignal(CanSignal* signal, cJSON* value,
        uint64_t (*writer)(CanSignal*, CanSignal*, int, cJSON*, bool*),
        CanSignal* signals, int signalCount) {
    bool send = true;
    if(writer == NULL) {
        if(signal->stateCount > 0) {
            writer = stateWriter;
        } else {
            writer = numberWriter;
        }
    }

    uint64_t data = writer(signal, signals, signalCount, value, &send);
    return sendCanSignal(signal, data, &send);
}

void processCanWriteQueue(CanBus* bus) {
    while(!QUEUE_EMPTY(CanMessage, &bus->sendQueue)) {
        CanMessage message = QUEUE_POP(CanMessage, &bus->sendQueue);
        debug("Sending CAN message id = 0x%03x, data = 0x", message.id);
        for(int i = 0; i < 8; i++) {
            debug("%02x ", ((uint8_t*)&message.data)[i]);
        }
        debug("\r\n");
        if(!sendCanMessage(bus, message)) {
            debug("Unable to send CAN message with id = 0x%x\r\n", message.id);
        }
    }
}
<commit_msg>Dereference "send" value to actually make correct determination.<commit_after>#include "canwrite.h"
#include "log.h"

QUEUE_DEFINE(CanMessage);

void checkWritePermission(CanSignal* signal, bool* send) {
    if(!signal->writable) {
        *send = false;
    }
}

uint64_t booleanWriter(CanSignal* signal, CanSignal* signals,
        int signalCount, cJSON* value, bool* send) {
    return booleanWriter(signal, signals, signalCount, value, send, 0);
}

uint64_t booleanWriter(CanSignal* signal, CanSignal* signals,
        int signalCount, cJSON* value, bool* send, uint64_t data) {
    checkWritePermission(signal, send);
    int intValue = 0;
    if(value->type == cJSON_False) {
        intValue = 0;
    } else if(value->type == cJSON_True) {
        intValue = 1;
    }
    return encodeCanSignal(signal, intValue, data);
}

uint64_t numberWriter(CanSignal* signal, CanSignal* signals,
        int signalCount, cJSON* value, bool* send) {
    return numberWriter(signal, signals, signalCount, value, send, 0);
}

uint64_t numberWriter(CanSignal* signal, CanSignal* signals,
        int signalCount, cJSON* value, bool* send, uint64_t data) {
    checkWritePermission(signal, send);
    return encodeCanSignal(signal, value->valuedouble, data);
}

uint64_t stateWriter(CanSignal* signal, CanSignal* signals,
        int signalCount, const char* value, bool* send, uint64_t data) {
    if(value == NULL) {
        debug("Can't write state of NULL -- not sending\r\n");
    } else {
        CanSignalState* signalState = lookupSignalState(value, signal, signals,
                signalCount);
        if(signalState != NULL) {
            checkWritePermission(signal, send);
            return encodeCanSignal(signal, signalState->value, data);
        } else {
            debug("Couldn't find a valid signal state for \"%s\"", value);
        }
    }
    *send = false;
    return 0;
}

uint64_t stateWriter(CanSignal* signal, CanSignal* signals,
        int signalCount, const char* value, bool* send) {
    return stateWriter(signal, signals, signalCount, value, send, 0);
}

uint64_t stateWriter(CanSignal* signal, CanSignal* signals,
        int signalCount, cJSON* value, bool* send, uint64_t data) {
    return stateWriter(signal, signals, signalCount, value->valuestring, send,
            data);
}

uint64_t stateWriter(CanSignal* signal, CanSignal* signals,
        int signalCount, cJSON* value, bool* send) {
    return stateWriter(signal, signals, signalCount, value, send, 0);
}

uint64_t encodeCanSignal(CanSignal* signal, float value) {
    return encodeCanSignal(signal, value, 0);
}

uint64_t encodeCanSignal(CanSignal* signal, float value, uint64_t data) {
    float rawValue = (value - signal->offset) / signal->factor;
    if(rawValue > 0) {
        // round up to avoid losing precision when we cast to an int
        rawValue += 0.5;
    }
    setBitField(&data, rawValue, signal->bitPosition, signal->bitSize);
    return data;
}

bool sendCanSignal(CanSignal* signal, uint64_t data, bool* send) {
    if(*send) {
        CanMessage message = {signal->messageId, data};
        QUEUE_PUSH(CanMessage, &signal->bus->sendQueue, message);
        return true;
    }
    debug("Not sending requested message %x\r\n", signal->messageId);
    return false;
}

bool sendCanSignal(CanSignal* signal, cJSON* value, CanSignal* signals,
        int signalCount) {
    uint64_t (*writer)(CanSignal*, CanSignal*, int, cJSON*, bool*)
        = signal->writeHandler;
    return sendCanSignal(signal, value, writer, signals, signalCount);
}

bool sendCanSignal(CanSignal* signal, cJSON* value,
        uint64_t (*writer)(CanSignal*, CanSignal*, int, cJSON*, bool*),
        CanSignal* signals, int signalCount) {
    bool send = true;
    if(writer == NULL) {
        if(signal->stateCount > 0) {
            writer = stateWriter;
        } else {
            writer = numberWriter;
        }
    }

    uint64_t data = writer(signal, signals, signalCount, value, &send);
    return sendCanSignal(signal, data, &send);
}

void processCanWriteQueue(CanBus* bus) {
    while(!QUEUE_EMPTY(CanMessage, &bus->sendQueue)) {
        CanMessage message = QUEUE_POP(CanMessage, &bus->sendQueue);
        debug("Sending CAN message id = 0x%03x, data = 0x", message.id);
        for(int i = 0; i < 8; i++) {
            debug("%02x ", ((uint8_t*)&message.data)[i]);
        }
        debug("\r\n");
        if(!sendCanMessage(bus, message)) {
            debug("Unable to send CAN message with id = 0x%x\r\n", message.id);
        }
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2017-2018 Tom van Dijk, Johannes Kepler University Linz
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <csignal>
#include <iomanip>
#include <iostream>
#include <fstream>
#include <sys/time.h>

#include <boost/algorithm/string/predicate.hpp>
#include <boost/iostreams/categories.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/bzip2.hpp>
#include <boost/iostreams/filter/gzip.hpp>

#include "cxxopts.hpp"
#include "game.hpp"
#include "oink.hpp"
#include "solvers.hpp"
#include "verifier.hpp"

using namespace pg;

/*------------------------------------------------------------------------*/

static double
wctime()
{
    struct timeval time;
    gettimeofday(&time, NULL);
    return time.tv_sec + 1E-6 * time.tv_usec;
}

static double t_start;

/*------------------------------------------------------------------------*/

// timestamp_filter adds a timestamp at the beginning of every line.
namespace io = boost::iostreams;
class timestamp_filter : public io::output_filter
{
public:
    timestamp_filter() {}
    struct category : io::output_filter::category, io::flushable_tag { };

    template<typename Sink> bool put(Sink& snk, char c);
    template<typename Device> void close(Device&);
    template<typename Sink> bool flush(Sink& snk);

private:
    bool is_start = true;
    char sz[16];
    const char* pos = NULL;
    const char* end = NULL;
};

template<typename Sink>
bool timestamp_filter::put(Sink& dest, char c)
{
    if (is_start) {
        if (c == '\n') return true;  // ignore consecutive endl
        is_start = false;
        pos = sz;
        end = sz + snprintf(sz, 16, "[% 8.2f] ", wctime() - t_start);
    }

    while (pos != end) {
        if (!io::put(dest, *pos)) return false;
        pos++;
    }

    if (!io::put(dest, c)) return false;
    if (c == '\n') is_start = true;

    return true;
}

template<typename Sink>
bool timestamp_filter::flush(Sink& dest)
{
    while (pos != end) {
        if (!io::put(dest, *pos)) return false;
        pos++;
    }

    return io::flush(dest);
}

template<typename Device>
void timestamp_filter::close(Device&)
{
    is_start = true;
    pos = end = NULL;
}

// global variable so signal handlers can work with it
io::filtering_ostream out;

/*------------------------------------------------------------------------*/

static void (*sig_int_handler)(int);
static void (*sig_segv_handler)(int);
static void (*sig_abrt_handler)(int);
static void (*sig_term_handler)(int);
static void (*sig_alrm_handler)(int);

static void
resetsighandlers(void)
{
    (void)signal(SIGINT, sig_int_handler);
    (void)signal(SIGSEGV, sig_segv_handler);
    (void)signal(SIGABRT, sig_abrt_handler);
    (void)signal(SIGTERM, sig_term_handler);
    (void)signal(SIGALRM, sig_alrm_handler);
}

static void
catchsig(int sig)
{
    // note: this can actually deadlock because we are writing to stdout...

    if (sig == SIGALRM) {
        resetsighandlers();
        out << std::endl << "terminated due to timeout" << std::endl;
        out.flush();
        exit(-1);
    } else if (sig == SIGINT) {
        // CTRL-C
        resetsighandlers();
        out << std::endl << "received INT signal" << std::endl;
        out.flush();
        exit(-1);
    } else if (sig == SIGABRT) {
        // really bad
        resetsighandlers();
        out << std::endl << "terminated due to ABORT signal" << std::endl;
        out.flush();
        raise(sig);
    } else {
        resetsighandlers();
        out << std::endl << "terminated due to signal " << sig << std::endl;
        out.flush();
        exit(-1);
    }
}

static void
setsighandlers(void)
{
    sig_int_handler = signal(SIGINT, catchsig);
    sig_segv_handler = signal(SIGSEGV, catchsig);
    sig_abrt_handler = signal(SIGABRT, catchsig);
    sig_term_handler = signal(SIGTERM, catchsig);
    sig_alrm_handler = signal(SIGALRM, catchsig);
}

/*------------------------------------------------------------------------*/

int main(int argc, char **argv)
{
    t_start = wctime();

    setsighandlers();

    cxxopts::Options opts(argv[0], "Parity game solver");
    opts.add_options()
        ("help", "Print help")
        ("t,trace", "Generate trace (with increasing verbosity)")
        ("v,verify", "Verify solution")
        ("p,print", "Print solution to stdout")
        ("i,input", "Input parity game", cxxopts::value<std::string>())
        ("sol", "Input solution", cxxopts::value<std::string>())
        ("o,output", "Output game or solution", cxxopts::value<std::string>())
        ("dot", "Write .dot file (before preprocessing)", cxxopts::value<std::string>())
        /* Preprocessing */
        ("inflate", "Inflate game")
        ("compress", "Compress game")
        ("no-single", "Do not solve single-parity games during preprocessing")
        ("no-loops", "Do not process self-loops during preprocessing")
        ("no-wcwc", "Do not solve winner-controlled winning cycles during preprocessing")
        /* Solving */
        ("scc", "Iteratively solve bottom SCCs")
        ("s,solver", "Use given solver (--solvers for info)", cxxopts::value<std::string>())
        ("solvers", "List available solvers")
        ("w,workers", "Number of workers for parallel code", cxxopts::value<int>())
        ("z,timeout", "Number of seconds for timeout", cxxopts::value<int>())
        ;

    /* Add solvers */
    Solvers solvers;
    for (unsigned id=0; id<solvers.count(); id++) {
        opts.add_options()(solvers.label(id), solvers.desc(id));
    }

    /* Parse command line */
    opts.parse_positional(std::vector<std::string>({"input", "output"}));
    opts.parse(argc, argv);

    if (opts.count("help")) {
        std::cout << opts.help() << std::endl;
        return 0;
    }

    if (opts.count("solvers")) {
        solvers.list(std::cout);
        return 0;
    }

    /* Setup timestamp filter */

    out.push(timestamp_filter());
    out.push(std::cout);

    /**
     * STEP 1
     * Read the game that must be solved.
     * (Supports bz2 and gz compression.)
     */

    Game pg;

    try {
        if (opts.count("input")) {
            std::string filename = opts["input"].as<std::string>();
            io::filtering_istream in;
            if (boost::algorithm::ends_with(filename, ".bz2")) in.push(io::bzip2_decompressor());
            if (boost::algorithm::ends_with(filename, ".gz")) in.push(io::gzip_decompressor());
            std::ifstream file(filename, std::ios_base::binary);
            in.push(file);
            pg.parse_pgsolver(in);
            file.close();
        } else {
            pg.parse_pgsolver(std::cin);
        }
        out << "parity game with " << pg.nodecount() << " nodes and " << pg.edgecount() << " edges." << std::endl;
    } catch (const char *err) {
        out << "parsing error: " << err << std::endl;
        return -1;
    }

    /**
     * STEP 2
     * Parse the (partial) solution.
     */

    try {
        if (opts.count("sol")) {
            std::ifstream file(opts["sol"].as<std::string>());
            pg.parse_solution(file);
            file.close();
            out << "solution parsed." << std::endl;
        }
    } catch (const char *err) {
        out << "parsing error: " << err << std::endl;
        return -1;
    }

    /**
     * STEP 3
     * If requested, write .dot file
     */

    if (opts.count("dot")) {
        std::ofstream file(opts["dot"].as<std::string>());
        pg.write_dot(file);
        file.close();
        out << "dot file written." << std::endl;
    }

    /**
     * STEP 4
     * Reindex the game so all nodes are in order of priority.
     * (Remember the mapping to reverse the reindex later.)
     */

    int *mapping = new int[pg.n_nodes];
    pg.reindex(mapping);
    out << "parity game reindexed" << std::endl;

    /**
     * STEP 5
     * Configure the solver.
     */

    Oink en(pg, out);
    en.setTrace(opts.count("t"));

    // preprocessing options
    if (opts.count("inflate")) en.setInflate();
    else if (opts.count("compress")) en.setCompress();
    else en.setRenumber();
    if (opts.count("no-single")) en.setSolveSingle(false);
    if (opts.count("no-loops")) en.setRemoveLoops(false);
    if (opts.count("no-wcwc")) en.setRemoveWCWC(false);

    // solver
    if (opts.count("solver")) {
        en.setSolver(solvers.id(opts["solver"].as<std::string>()));
    } else {
        en.setSolver("npp"); // default solver :)
        for (unsigned id=0; id<solvers.count(); id++) {
            if (opts.count(solvers.label(id))) en.setSolver(id);
        }
    }

    // solving options
    if (opts.count("scc")) en.setBottomSCC(true);
    if (opts.count("workers")) en.setWorkers(opts["workers"].as<int>());

    /**
     * STEP 6
     * Run the solver and report the time.
     */

    if (opts.count("timeout")) alarm(opts["timeout"].as<int>());
    double begin = wctime();
    en.run();
    double end = wctime();
    out << "solving took " << std::fixed << (end-begin) << " sec." << std::endl;

    /**
     * STEP 7
     * Verify the solution.
     */

    if (opts.count("v")) {
        try {
            out << "verifying solution..." << std::endl;
            Verifier v(&pg, out);
            double vbegin = wctime();
            v.verify(true, opts.count("qpt")==0, true);
            double vend = wctime();
            out << "solution verified (" << v.n_strategies << " strategies)." << std::endl;
            out << "verification took " << std::fixed << (vend - vbegin) << " sec." << std::endl;
        } catch (const char *err) {
            out << "verification error: " << err << std::endl;
            return -1;
        }
    }

    /**
     * STEP 8
     * Revert reindex if we need to output.
     */

    if (opts.count("output") or opts.count("p")) pg.permute(mapping);

    if (opts.count("output")) {
        // write solution to file
        if (opts.count("output")) {
            std::ofstream file(opts["output"].as<std::string>());
            pg.write_sol(file);
        }
    }

    if (opts.count("p")) {
        // print winning nodes
        bool banner = false;
        for (int i=0; i<pg.n_nodes; i++) {
            if (pg.solved[i] and pg.winner[i] == 0) {
                if (!banner) out << "won by even:";
                banner = true;
                out << " " << i; // << "(" << pg.priority[i] << ")";
            }
        }
        if (banner) out << std::endl;
        banner = false;
        for (int i=0; i<pg.n_nodes; i++) {
            if (pg.solved[i] and pg.winner[i] == 1) {
                if (!banner) out << "won by odd:";
                banner = true;
                out << " " << i; // << "(" << pg.priority[i] << ")";
            }
        }
        if (banner) out << std::endl;
    }

    delete[] mapping;

    resetsighandlers();
    return 0;
}
<commit_msg>Solver now reports won vertices by label instead of priority<commit_after>/*
 * Copyright 2017-2018 Tom van Dijk, Johannes Kepler University Linz
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <csignal>
#include <iomanip>
#include <iostream>
#include <fstream>
#include <sys/time.h>

#include <boost/algorithm/string/predicate.hpp>
#include <boost/iostreams/categories.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/bzip2.hpp>
#include <boost/iostreams/filter/gzip.hpp>

#include "cxxopts.hpp"
#include "game.hpp"
#include "oink.hpp"
#include "solvers.hpp"
#include "verifier.hpp"

using namespace pg;

/*------------------------------------------------------------------------*/

static double
wctime()
{
    struct timeval time;
    gettimeofday(&time, NULL);
    return time.tv_sec + 1E-6 * time.tv_usec;
}

static double t_start;

/*------------------------------------------------------------------------*/

// timestamp_filter adds a timestamp at the beginning of every line.
namespace io = boost::iostreams;
class timestamp_filter : public io::output_filter
{
public:
    timestamp_filter() {}
    struct category : io::output_filter::category, io::flushable_tag { };

    template<typename Sink> bool put(Sink& snk, char c);
    template<typename Device> void close(Device&);
    template<typename Sink> bool flush(Sink& snk);

private:
    bool is_start = true;
    char sz[16];
    const char* pos = NULL;
    const char* end = NULL;
};

template<typename Sink>
bool timestamp_filter::put(Sink& dest, char c)
{
    if (is_start) {
        if (c == '\n') return true;  // ignore consecutive endl
        is_start = false;
        pos = sz;
        end = sz + snprintf(sz, 16, "[% 8.2f] ", wctime() - t_start);
    }

    while (pos != end) {
        if (!io::put(dest, *pos)) return false;
        pos++;
    }

    if (!io::put(dest, c)) return false;
    if (c == '\n') is_start = true;

    return true;
}

template<typename Sink>
bool timestamp_filter::flush(Sink& dest)
{
    while (pos != end) {
        if (!io::put(dest, *pos)) return false;
        pos++;
    }

    return io::flush(dest);
}

template<typename Device>
void timestamp_filter::close(Device&)
{
    is_start = true;
    pos = end = NULL;
}

// global variable so signal handlers can work with it
io::filtering_ostream out;

/*------------------------------------------------------------------------*/

static void (*sig_int_handler)(int);
static void (*sig_segv_handler)(int);
static void (*sig_abrt_handler)(int);
static void (*sig_term_handler)(int);
static void (*sig_alrm_handler)(int);

static void
resetsighandlers(void)
{
    (void)signal(SIGINT, sig_int_handler);
    (void)signal(SIGSEGV, sig_segv_handler);
    (void)signal(SIGABRT, sig_abrt_handler);
    (void)signal(SIGTERM, sig_term_handler);
    (void)signal(SIGALRM, sig_alrm_handler);
}

static void
catchsig(int sig)
{
    // note: this can actually deadlock because we are writing to stdout...

    if (sig == SIGALRM) {
        resetsighandlers();
        out << std::endl << "terminated due to timeout" << std::endl;
        out.flush();
        exit(-1);
    } else if (sig == SIGINT) {
        // CTRL-C
        resetsighandlers();
        out << std::endl << "received INT signal" << std::endl;
        out.flush();
        exit(-1);
    } else if (sig == SIGABRT) {
        // really bad
        resetsighandlers();
        out << std::endl << "terminated due to ABORT signal" << std::endl;
        out.flush();
        raise(sig);
    } else {
        resetsighandlers();
        out << std::endl << "terminated due to signal " << sig << std::endl;
        out.flush();
        exit(-1);
    }
}

static void
setsighandlers(void)
{
    sig_int_handler = signal(SIGINT, catchsig);
    sig_segv_handler = signal(SIGSEGV, catchsig);
    sig_abrt_handler = signal(SIGABRT, catchsig);
    sig_term_handler = signal(SIGTERM, catchsig);
    sig_alrm_handler = signal(SIGALRM, catchsig);
}

/*------------------------------------------------------------------------*/

int main(int argc, char **argv)
{
    t_start = wctime();

    setsighandlers();

    cxxopts::Options opts(argv[0], "Parity game solver");
    opts.add_options()
        ("help", "Print help")
        ("t,trace", "Generate trace (with increasing verbosity)")
        ("v,verify", "Verify solution")
        ("p,print", "Print solution to stdout")
        ("i,input", "Input parity game", cxxopts::value<std::string>())
        ("sol", "Input solution", cxxopts::value<std::string>())
        ("o,output", "Output game or solution", cxxopts::value<std::string>())
        ("dot", "Write .dot file (before preprocessing)", cxxopts::value<std::string>())
        /* Preprocessing */
        ("inflate", "Inflate game")
        ("compress", "Compress game")
        ("no-single", "Do not solve single-parity games during preprocessing")
        ("no-loops", "Do not process self-loops during preprocessing")
        ("no-wcwc", "Do not solve winner-controlled winning cycles during preprocessing")
        /* Solving */
        ("scc", "Iteratively solve bottom SCCs")
        ("s,solver", "Use given solver (--solvers for info)", cxxopts::value<std::string>())
        ("solvers", "List available solvers")
        ("w,workers", "Number of workers for parallel code", cxxopts::value<int>())
        ("z,timeout", "Number of seconds for timeout", cxxopts::value<int>())
        ;

    /* Add solvers */
    Solvers solvers;
    for (unsigned id=0; id<solvers.count(); id++) {
        opts.add_options()(solvers.label(id), solvers.desc(id));
    }

    /* Parse command line */
    opts.parse_positional(std::vector<std::string>({"input", "output"}));
    opts.parse(argc, argv);

    if (opts.count("help")) {
        std::cout << opts.help() << std::endl;
        return 0;
    }

    if (opts.count("solvers")) {
        solvers.list(std::cout);
        return 0;
    }

    /* Setup timestamp filter */

    out.push(timestamp_filter());
    out.push(std::cout);

    /**
     * STEP 1
     * Read the game that must be solved.
     * (Supports bz2 and gz compression.)
     */

    Game pg;

    try {
        if (opts.count("input")) {
            std::string filename = opts["input"].as<std::string>();
            io::filtering_istream in;
            if (boost::algorithm::ends_with(filename, ".bz2")) in.push(io::bzip2_decompressor());
            if (boost::algorithm::ends_with(filename, ".gz")) in.push(io::gzip_decompressor());
            std::ifstream file(filename, std::ios_base::binary);
            in.push(file);
            pg.parse_pgsolver(in);
            file.close();
        } else {
            pg.parse_pgsolver(std::cin);
        }
        out << "parity game with " << pg.nodecount() << " nodes and " << pg.edgecount() << " edges." << std::endl;
    } catch (const char *err) {
        out << "parsing error: " << err << std::endl;
        return -1;
    }

    /**
     * STEP 2
     * Parse the (partial) solution.
     */

    try {
        if (opts.count("sol")) {
            std::ifstream file(opts["sol"].as<std::string>());
            pg.parse_solution(file);
            file.close();
            out << "solution parsed." << std::endl;
        }
    } catch (const char *err) {
        out << "parsing error: " << err << std::endl;
        return -1;
    }

    /**
     * STEP 3
     * If requested, write .dot file
     */

    if (opts.count("dot")) {
        std::ofstream file(opts["dot"].as<std::string>());
        pg.write_dot(file);
        file.close();
        out << "dot file written." << std::endl;
    }

    /**
     * STEP 4
     * Reindex the game so all nodes are in order of priority.
     * (Remember the mapping to reverse the reindex later.)
     */

    int *mapping = new int[pg.n_nodes];
    pg.reindex(mapping);
    out << "parity game reindexed" << std::endl;

    /**
     * STEP 5
     * Configure the solver.
     */

    Oink en(pg, out);
    en.setTrace(opts.count("t"));

    // preprocessing options
    if (opts.count("inflate")) en.setInflate();
    else if (opts.count("compress")) en.setCompress();
    else en.setRenumber();
    if (opts.count("no-single")) en.setSolveSingle(false);
    if (opts.count("no-loops")) en.setRemoveLoops(false);
    if (opts.count("no-wcwc")) en.setRemoveWCWC(false);

    // solver
    if (opts.count("solver")) {
        en.setSolver(solvers.id(opts["solver"].as<std::string>()));
    } else {
        en.setSolver("npp"); // default solver :)
        for (unsigned id=0; id<solvers.count(); id++) {
            if (opts.count(solvers.label(id))) en.setSolver(id);
        }
    }

    // solving options
    if (opts.count("scc")) en.setBottomSCC(true);
    if (opts.count("workers")) en.setWorkers(opts["workers"].as<int>());

    /**
     * STEP 6
     * Run the solver and report the time.
     */

    if (opts.count("timeout")) alarm(opts["timeout"].as<int>());
    double begin = wctime();
    en.run();
    double end = wctime();
    out << "solving took " << std::fixed << (end-begin) << " sec." << std::endl;

    /**
     * STEP 7
     * Verify the solution.
     */

    if (opts.count("v")) {
        try {
            out << "verifying solution..." << std::endl;
            Verifier v(&pg, out);
            double vbegin = wctime();
            v.verify(true, opts.count("qpt")==0, true);
            double vend = wctime();
            out << "solution verified (" << v.n_strategies << " strategies)." << std::endl;
            out << "verification took " << std::fixed << (vend - vbegin) << " sec." << std::endl;
        } catch (const char *err) {
            out << "verification error: " << err << std::endl;
            return -1;
        }
    }

    /**
     * STEP 8
     * Revert reindex if we need to output.
     */

    if (opts.count("output") or opts.count("p")) pg.permute(mapping);

    if (opts.count("output")) {
        // write solution to file
        if (opts.count("output")) {
            std::ofstream file(opts["output"].as<std::string>());
            pg.write_sol(file);
        }
    }

    if (opts.count("p")) {
        // print winning nodes
        bool banner = false;
        for (int i=0; i<pg.n_nodes; i++) {
            if (pg.solved[i] and pg.winner[i] == 0) {
                if (!banner) out << "won by even:";
                banner = true;
                out << " " << pg.label[i];
            }
        }
        if (banner) out << std::endl;
        banner = false;
        for (int i=0; i<pg.n_nodes; i++) {
            if (pg.solved[i] and pg.winner[i] == 1) {
                if (!banner) out << "won by odd:";
                banner = true;
                out << " " << pg.label[i];
            }
        }
        if (banner) out << std::endl;
    }

    delete[] mapping;

    resetsighandlers();
    return 0;
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/isteps/istep06/host_gard.C $                          */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2017                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

#include <hwas/common/hwas.H>
#include <hwas/common/hwasCommon.H>
#include <hwas/common/hwas_reasoncodes.H>
#include <hwas/hwasPlat.H>

#include <hwas/common/deconfigGard.H>

#include <initservice/taskargs.H>
#include <initservice/isteps_trace.H>
#include <initservice/initserviceif.H>
#include <isteps/hwpisteperror.H>

#include <targeting/attrsync.H>
#include <targeting/namedtarget.H>

#include <sbe/sbeif.H>
#include <sbe/sbe_update.H>

//  targeting support.
#include  <targeting/common/utilFilter.H>
#include  <targeting/common/commontargeting.H>
#include  <targeting/common/entitypath.H>

#include  <errl/errludtarget.H>

#include <console/consoleif.H>

// Custom compile configs
#include <config.h>

#ifdef CONFIG_DRTM
#include <secureboot/drtm.H>
#endif

#ifdef CONFIG_ENABLE_CHECKSTOP_ANALYSIS
  #include <diag/attn/attn.H>
#endif

namespace ISTEP_06
{

void* host_gard( void *io_pArgs )
{
    TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "host_gard entry" );
    errlHndl_t l_err;
    ISTEP_ERROR::IStepError l_stepError;

    do {
        TARGETING::Target* l_pTopLevel = NULL;
        TARGETING::targetService().getTopLevelTarget( l_pTopLevel );
        assert(l_pTopLevel, "host_gard: no TopLevelTarget");

#ifdef CONFIG_ENABLE_CHECKSTOP_ANALYSIS
        TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
                   INFO_MRK"host_gard: invoke PRD to check for previous CS" );

        l_err = ATTN::checkForCSAttentions();
        if ( NULL != l_err )
        {
            TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
                       ERR_MRK"host_gard: error from checkForCSAttentions" );
            // commit and continue
            errlCommit (l_err, ISTEP_COMP_ID);
        }
#endif

        // Check whether we're in MPIPL mode
        if (l_pTopLevel->getAttr<TARGETING::ATTR_IS_MPIPL_HB>())
        {
            TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
                      "host_gard: MPIPL mode");

            // we only want EX units to be processed
            TARGETING::PredicateCTM l_exFilter(TARGETING::CLASS_UNIT,
                                           TARGETING::TYPE_EX);
            l_err = HWAS::collectGard(&l_exFilter);
            if (l_err)
            {
               TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,"host_gard: "
                               "collectGard returned error; breaking out");
                break;
            }
        }
        else
        {
            TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
                      "host_gard: Normal IPL mode");

            l_err = HWAS::collectGard();
            if(l_err)
            {
                TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,"host_gard: "
                   "collectGard returned error; breaking out");
                break;
            }
        }

        // Put out some helpful messages that show which targets are usable
        std::map<TARGETING::TYPE,uint64_t> l_funcData;
        for (auto target : TARGETING::targetService())
        {
            if (!(target->getAttr<TARGETING::ATTR_HWAS_STATE>().functional))
            {
                continue;
            }
            TARGETING::TYPE l_type =target->getAttr<TARGETING::ATTR_TYPE>();
            TARGETING::ATTR_FAPI_POS_type l_pos = 0;
            if( target->tryGetAttr<TARGETING::ATTR_FAPI_POS>(l_pos) )
            {
                l_funcData[l_type] |= (0x8000000000000000 >> l_pos);
            }
        }
        TARGETING::EntityPath l_epath;
        for( auto l_data : l_funcData)
        {
            auto l_type = l_data.first;
            uint64_t l_val = l_data.second;
            //Only want to display procs, dimms, and cores
            if((l_type != TARGETING::TYPE_DIMM) &&
               (l_type != TARGETING::TYPE_PROC) &&
               (l_type != TARGETING::TYPE_CORE))
            {
                continue;
            }
            TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
                      "FUNCTIONAL> %s[%.2X]=%.8X%.8X",
                      l_epath.pathElementTypeAsString(l_type),
                      l_type,
                      l_val>>32, l_val&0xFFFFFFFF);

#if (!defined(CONFIG_CONSOLE_OUTPUT_TRACE) && defined(CONFIG_CONSOLE))
            CONSOLE::displayf("HWAS", "FUNCTIONAL> %s[%.2X]=%.8X%.8X",
                              l_epath.pathElementTypeAsString(l_type),
                              l_type,
                              l_val>>32,
                              l_val&0xFFFFFFFF );
#endif
            }

        //  check and see if we still have enough hardware to continue
        l_err = HWAS::checkMinimumHardware();
        if(l_err)
        {
            TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
                ERR_MRK"host_gard: "
                "check minimum hardware returned error; breaking out");
            break;
        }

        // If targets are deconfigured as a result of host_gard, they are
        // done so using the PLID as the reason for deconfiguration.  This
        // triggers the reconfigure loop attribute to be set, which causes
        // undesirable behavior, so we need to reset it here:

        // Read current value
        TARGETING::ATTR_RECONFIGURE_LOOP_type l_reconfigAttr =
            l_pTopLevel->getAttr<TARGETING::ATTR_RECONFIGURE_LOOP>();
        // Turn off deconfigure bit
        l_reconfigAttr &= ~TARGETING::RECONFIGURE_LOOP_DECONFIGURE;
        // Write back to attribute
        l_pTopLevel->setAttr<TARGETING::ATTR_RECONFIGURE_LOOP>
                (l_reconfigAttr);

        // Send message to FSP with HUID of master core
        msg_t * core_msg = msg_allocate();
        core_msg->type = SBE::MSG_IPL_MASTER_CORE;
        const TARGETING::Target*  l_masterCore  = TARGETING::getMasterCore( );

         /*@ errorlog tag
          *  @errortype      ERRL_SEV_CRITICAL_SYS_TERM
          *  @moduleid       ISTEP::MOD_HOST_GARD
          *  @reasoncode     ISTEP::RC_MASTER_CORE_NULL
          *  @userdata1      0
          *  @userdata2      0
          *  @devdesc        host_gard: no masterCore found
          */
        if (l_masterCore == NULL)
        {
            TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, ERR_MRK"host_gard: "
                "No masterCore Found" );
            const bool hbSwError = true;
            l_err = new ERRORLOG::ErrlEntry
                    (ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM,
                     ISTEP::MOD_HOST_GARD,
                     ISTEP::RC_MASTER_CORE_NULL,
                     0, 0, hbSwError);
            break;
        }

        core_msg->data[0] = TARGETING::get_huid(l_masterCore);
        core_msg->extra_data = NULL;

        // TODO RTC 149318 Once HWSV is updated to take the master core
        // from data[0], stop sending the EX in data[1].
        // Set data[1] to 0 instead of the following.
        {
            // Get the EX chip associated with the master core as that is the
            // chip that has the MASTER_EX attribute associated with it
            TARGETING::TargetHandleList targetList;
            getParentAffinityTargets(targetList,
                             l_masterCore,
                             TARGETING::CLASS_UNIT,
                             TARGETING::TYPE_EX);
            assert(targetList.size() == 1,
             "host_gard: Incorrect EX chip(s) associated with masterCore");
            core_msg->data[1] = TARGETING::get_huid( targetList[0] );
            TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,"host_gard: "
                  "Sending MSG_MASTER_CORE message with EX HUID %08x",
                  core_msg->data[1]);
        }
        TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,"host_gard: "
              "Sending MSG_MASTER_CORE message with HUID %08x",
              core_msg->data[0]);
        l_err = MBOX::send(MBOX::IPL_SERVICE_QUEUE,core_msg);
        if (l_err)
        {
            TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, ERR_MRK"host_gard: "
                       "MBOX::send failed sending Master Core message");
            msg_free(core_msg);
            break;
        }

#ifdef CONFIG_DRTM
        bool drtmMpipl = false;
        SECUREBOOT::DRTM::isDrtmMpipl(drtmMpipl);
        if(drtmMpipl)
        {
            l_err = SECUREBOOT::DRTM::validateDrtmHwSignature();
            if(l_err)
            {
                TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, ERR_MRK
                    "host_gard: Failed in call to validateDrtmHwSignature");
                break;
            }
        }
#endif

    } while (0);

    if (l_err)
    {
        // Create IStep error log and cross reference occurred error
        l_stepError.addErrorDetails( l_err );
        // Commit Error
        errlCommit (l_err, ISTEP_COMP_ID);
    }

    TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "host_gard exit" );
    return l_stepError.getErrorHandle();
}

};
<commit_msg>Update SBE if there is a gard to the master core in OpenPower<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/isteps/istep06/host_gard.C $                          */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2017                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

#include <hwas/common/hwas.H>
#include <hwas/common/hwasCommon.H>
#include <hwas/common/hwas_reasoncodes.H>
#include <hwas/hwasPlat.H>

#include <hwas/common/deconfigGard.H>

#include <initservice/taskargs.H>
#include <initservice/isteps_trace.H>
#include <initservice/initserviceif.H>
#include <isteps/hwpisteperror.H>

#include <targeting/attrsync.H>
#include <targeting/namedtarget.H>

#include <sbe/sbeif.H>
#include <sbe/sbe_update.H>

//  targeting support.
#include  <targeting/common/utilFilter.H>
#include  <targeting/common/commontargeting.H>
#include  <targeting/common/entitypath.H>

#include  <errl/errludtarget.H>

#include <console/consoleif.H>

// Custom compile configs
#include <config.h>

#ifdef CONFIG_DRTM
#include <secureboot/drtm.H>
#endif

#ifdef CONFIG_ENABLE_CHECKSTOP_ANALYSIS
  #include <diag/attn/attn.H>
#endif

namespace ISTEP_06
{

void* host_gard( void *io_pArgs )
{
    TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "host_gard entry" );
    errlHndl_t l_err;
    ISTEP_ERROR::IStepError l_stepError;

    do {
        TARGETING::Target* l_pTopLevel = NULL;
        TARGETING::targetService().getTopLevelTarget( l_pTopLevel );
        assert(l_pTopLevel, "host_gard: no TopLevelTarget");

#ifdef CONFIG_ENABLE_CHECKSTOP_ANALYSIS
        TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
                   INFO_MRK"host_gard: invoke PRD to check for previous CS" );

        l_err = ATTN::checkForCSAttentions();
        if ( NULL != l_err )
        {
            TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
                       ERR_MRK"host_gard: error from checkForCSAttentions" );
            // commit and continue
            errlCommit (l_err, ISTEP_COMP_ID);
        }
#endif

        // Check whether we're in MPIPL mode
        if (l_pTopLevel->getAttr<TARGETING::ATTR_IS_MPIPL_HB>())
        {
            TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
                      "host_gard: MPIPL mode");

            // we only want EX units to be processed
            TARGETING::PredicateCTM l_exFilter(TARGETING::CLASS_UNIT,
                                           TARGETING::TYPE_EX);
            l_err = HWAS::collectGard(&l_exFilter);
            if (l_err)
            {
               TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,"host_gard: "
                               "collectGard returned error; breaking out");
                break;
            }
        }
        else
        {
            TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
                      "host_gard: Normal IPL mode");

            l_err = HWAS::collectGard();
            if(l_err)
            {
                TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,"host_gard: "
                   "collectGard returned error; breaking out");
                break;
            }
        }

        // Put out some helpful messages that show which targets are usable
        std::map<TARGETING::TYPE,uint64_t> l_funcData;
        for (auto target : TARGETING::targetService())
        {
            if (!(target->getAttr<TARGETING::ATTR_HWAS_STATE>().functional))
            {
                continue;
            }
            TARGETING::TYPE l_type =target->getAttr<TARGETING::ATTR_TYPE>();
            TARGETING::ATTR_FAPI_POS_type l_pos = 0;
            if( target->tryGetAttr<TARGETING::ATTR_FAPI_POS>(l_pos) )
            {
                l_funcData[l_type] |= (0x8000000000000000 >> l_pos);
            }
        }
        TARGETING::EntityPath l_epath;
        for( auto l_data : l_funcData)
        {
            auto l_type = l_data.first;
            uint64_t l_val = l_data.second;
            //Only want to display procs, dimms, and cores
            if((l_type != TARGETING::TYPE_DIMM) &&
               (l_type != TARGETING::TYPE_PROC) &&
               (l_type != TARGETING::TYPE_CORE))
            {
                continue;
            }
            TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
                      "FUNCTIONAL> %s[%.2X]=%.8X%.8X",
                      l_epath.pathElementTypeAsString(l_type),
                      l_type,
                      l_val>>32, l_val&0xFFFFFFFF);

#if (!defined(CONFIG_CONSOLE_OUTPUT_TRACE) && defined(CONFIG_CONSOLE))
            CONSOLE::displayf("HWAS", "FUNCTIONAL> %s[%.2X]=%.8X%.8X",
                              l_epath.pathElementTypeAsString(l_type),
                              l_type,
                              l_val>>32,
                              l_val&0xFFFFFFFF );
#endif
            }

        //  check and see if we still have enough hardware to continue
        l_err = HWAS::checkMinimumHardware();
        if(l_err)
        {
            TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
                ERR_MRK"host_gard: "
                "check minimum hardware returned error; breaking out");
            break;
        }

        // If targets are deconfigured as a result of host_gard, they are
        // done so using the PLID as the reason for deconfiguration.  This
        // triggers the reconfigure loop attribute to be set, which causes
        // undesirable behavior, so we need to reset it here:

        // Read current value
        TARGETING::ATTR_RECONFIGURE_LOOP_type l_reconfigAttr =
            l_pTopLevel->getAttr<TARGETING::ATTR_RECONFIGURE_LOOP>();
        // Turn off deconfigure bit
        l_reconfigAttr &= ~TARGETING::RECONFIGURE_LOOP_DECONFIGURE;
        // Write back to attribute
        l_pTopLevel->setAttr<TARGETING::ATTR_RECONFIGURE_LOOP>
                (l_reconfigAttr);

        // Send message to FSP with HUID of master core
        msg_t * core_msg = msg_allocate();
        core_msg->type = SBE::MSG_IPL_MASTER_CORE;
        const TARGETING::Target*  l_masterCore  = TARGETING::getMasterCore( );

        if (l_masterCore == NULL)
        {
            TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, ERR_MRK"host_gard: "
                 "No masterCore Found." );
            if( INITSERVICE::spBaseServicesEnabled() )
            {
                const bool hbSwError = true;
                l_err = new ERRORLOG::ErrlEntry
                    (ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM,
                     ISTEP::MOD_HOST_GARD,
                     ISTEP::RC_MASTER_CORE_NULL,
                     0, 0, hbSwError);
            }
            else
            {
                // The masterCore may have a GARD record, update SBE
                // and let it reboot to another core
                TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, ERR_MRK"host_gard: "
                    "Calling updateProcessorSbeSeeproms..." );
                l_err = SBE::updateProcessorSbeSeeproms();
                if(l_err)
                {
                    TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
                        "host_gard: Error calling updateProcessorSbeSeeproms");
                }
            }
            break;
        }

        core_msg->data[0] = TARGETING::get_huid(l_masterCore);
        core_msg->extra_data = NULL;

        // TODO RTC 149318 Once HWSV is updated to take the master core
        // from data[0], stop sending the EX in data[1].
        // Set data[1] to 0 instead of the following.
        {
            // Get the EX chip associated with the master core as that is the
            // chip that has the MASTER_EX attribute associated with it
            TARGETING::TargetHandleList targetList;
            getParentAffinityTargets(targetList,
                             l_masterCore,
                             TARGETING::CLASS_UNIT,
                             TARGETING::TYPE_EX);
            assert(targetList.size() == 1,
             "host_gard: Incorrect EX chip(s) associated with masterCore");
            core_msg->data[1] = TARGETING::get_huid( targetList[0] );
            TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,"host_gard: "
                  "Sending MSG_MASTER_CORE message with EX HUID %08x",
                  core_msg->data[1]);
        }
        TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,"host_gard: "
              "Sending MSG_MASTER_CORE message with HUID %08x",
              core_msg->data[0]);
        l_err = MBOX::send(MBOX::IPL_SERVICE_QUEUE,core_msg);
        if (l_err)
        {
            TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, ERR_MRK"host_gard: "
                       "MBOX::send failed sending Master Core message");
            msg_free(core_msg);
            break;
        }

#ifdef CONFIG_DRTM
        bool drtmMpipl = false;
        SECUREBOOT::DRTM::isDrtmMpipl(drtmMpipl);
        if(drtmMpipl)
        {
            l_err = SECUREBOOT::DRTM::validateDrtmHwSignature();
            if(l_err)
            {
                TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, ERR_MRK
                    "host_gard: Failed in call to validateDrtmHwSignature");
                break;
            }
        }
#endif

    } while (0);

    if (l_err)
    {
        // Create IStep error log and cross reference occurred error
        l_stepError.addErrorDetails( l_err );
        // Commit Error
        errlCommit (l_err, ISTEP_COMP_ID);
    }

    TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "host_gard exit" );
    return l_stepError.getErrorHandle();
}

};
<|endoftext|>


<commit_before>/*
   This file is part of KDE Kontact.

   Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
   Copyright (c) 2003 Daniel Molkentin <molkentin@kde.org>

   This library 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 library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#include "summary.h"

#include <qimage.h>
#include <q3dragobject.h>
#include <q3hbox.h>
#include <qfont.h>
#include <qlabel.h>
#include <qpainter.h>
//Added by qt3to4:
#include <QPixmap>
#include <QMouseEvent>
#include <QDragEnterEvent>
#include <QDropEvent>

#include <kiconloader.h>
#include <kdialog.h>

using namespace Kontact;

Summary::Summary( QWidget *parent, const char *name )
  : QWidget( parent, name )
{
  setAcceptDrops( true );
}

Summary::~Summary()
{
}

QWidget* Summary::createHeader(QWidget *parent, const QPixmap& icon, const QString& heading)
{
  Q3HBox* hbox = new Q3HBox( parent );
  hbox->setMargin( 2 );

  QFont boldFont;
  boldFont.setBold( true );
  boldFont.setPointSize( boldFont.pointSize() + 2 );

  QLabel *label = new QLabel( hbox );
  label->setPixmap( icon );
  label->setFixedSize( label->sizeHint() );
  label->setPaletteBackgroundColor( colorGroup().mid() );
  label->setAcceptDrops( true );

  label = new QLabel( heading, hbox );
  label->setAlignment( Qt::AlignLeft|Qt::AlignVCenter );
  label->setIndent( KDialog::spacingHint() );
  label->setFont( boldFont );
  label->setPaletteForegroundColor( colorGroup().light() );
  label->setPaletteBackgroundColor( colorGroup().mid() );

  hbox->setPaletteBackgroundColor( colorGroup().mid() );

  hbox->setMaximumHeight( hbox->minimumSizeHint().height() );

  return hbox;
}

void Summary::mousePressEvent( QMouseEvent *event )
{
  mDragStartPoint = event->pos();

  QWidget::mousePressEvent( event );
}

void Summary::mouseMoveEvent( QMouseEvent *event )
{
  if ( (event->state() & Qt::LeftButton) &&
       (event->pos() - mDragStartPoint).manhattanLength() > 4 ) {

    Q3DragObject *drag = new Q3TextDrag( "", this, "SummaryWidgetDrag" );

    QPixmap pm = QPixmap::grabWidget( this );
    if ( pm.width() > 300 )
      pm = pm.convertToImage().smoothScale( 300, 300, Qt::KeepAspectRatio );

    QPainter painter;
    painter.begin( &pm );
    painter.setPen( Qt::gray );
    painter.drawRect( 0, 0, pm.width(), pm.height() );
    painter.end();
    drag->setPixmap( pm );
    drag->dragMove();
  } else
    QWidget::mouseMoveEvent( event );
}

void Summary::dragEnterEvent( QDragEnterEvent *event )
{
  event->accept( Q3TextDrag::canDecode( event ) );
}

void Summary::dropEvent( QDropEvent *event )
{
  int alignment = (event->pos().y() < (height() / 2) ? Qt::AlignTop : Qt::AlignBottom);
  emit summaryWidgetDropped( this, event->source(), alignment );
}

#include "summary.moc"
<commit_msg>Q3HBox--<commit_after>/*
   This file is part of KDE Kontact.

   Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
   Copyright (c) 2003 Daniel Molkentin <molkentin@kde.org>

   This library 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 library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#include "summary.h"

#include <qimage.h>
#include <q3dragobject.h>
#include <khbox.h>
#include <qfont.h>
#include <qlabel.h>
#include <qpainter.h>
//Added by qt3to4:
#include <QPixmap>
#include <QMouseEvent>
#include <QDragEnterEvent>
#include <QDropEvent>

#include <kiconloader.h>
#include <kdialog.h>

using namespace Kontact;

Summary::Summary( QWidget *parent, const char *name )
  : QWidget( parent, name )
{
  setAcceptDrops( true );
}

Summary::~Summary()
{
}

QWidget* Summary::createHeader(QWidget *parent, const QPixmap& icon, const QString& heading)
{
  KHBox* hbox = new KHBox( parent );
  hbox->setMargin( 2 );

  QFont boldFont;
  boldFont.setBold( true );
  boldFont.setPointSize( boldFont.pointSize() + 2 );

  QLabel *label = new QLabel( hbox );
  label->setPixmap( icon );
  label->setFixedSize( label->sizeHint() );
  label->setPaletteBackgroundColor( colorGroup().mid() );
  label->setAcceptDrops( true );

  label = new QLabel( heading, hbox );
  label->setAlignment( Qt::AlignLeft|Qt::AlignVCenter );
  label->setIndent( KDialog::spacingHint() );
  label->setFont( boldFont );
  label->setPaletteForegroundColor( colorGroup().light() );
  label->setPaletteBackgroundColor( colorGroup().mid() );

  hbox->setPaletteBackgroundColor( colorGroup().mid() );

  hbox->setMaximumHeight( hbox->minimumSizeHint().height() );

  return hbox;
}

void Summary::mousePressEvent( QMouseEvent *event )
{
  mDragStartPoint = event->pos();

  QWidget::mousePressEvent( event );
}

void Summary::mouseMoveEvent( QMouseEvent *event )
{
  if ( (event->state() & Qt::LeftButton) &&
       (event->pos() - mDragStartPoint).manhattanLength() > 4 ) {

    Q3DragObject *drag = new Q3TextDrag( "", this, "SummaryWidgetDrag" );

    QPixmap pm = QPixmap::grabWidget( this );
    if ( pm.width() > 300 )
      pm = pm.convertToImage().smoothScale( 300, 300, Qt::KeepAspectRatio );

    QPainter painter;
    painter.begin( &pm );
    painter.setPen( Qt::gray );
    painter.drawRect( 0, 0, pm.width(), pm.height() );
    painter.end();
    drag->setPixmap( pm );
    drag->dragMove();
  } else
    QWidget::mouseMoveEvent( event );
}

void Summary::dragEnterEvent( QDragEnterEvent *event )
{
  event->accept( Q3TextDrag::canDecode( event ) );
}

void Summary::dropEvent( QDropEvent *event )
{
  int alignment = (event->pos().y() < (height() / 2) ? Qt::AlignTop : Qt::AlignBottom);
  emit summaryWidgetDropped( this, event->source(), alignment );
}

#include "summary.moc"
<|endoftext|>


<commit_before>/*
    This file is part of KOrganizer.
    Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

// $Id$

#include <qlayout.h>
#include <qtextbrowser.h>
#include <qtextcodec.h>
#include <qfileinfo.h>
#include <qlabel.h>

#include <kglobal.h>
#include <klocale.h>
#include <kdebug.h>
#include <kiconloader.h>
#include <kmessagebox.h>

#include <libkcal/calendar.h>

#ifndef KORG_NOPRINTER
#include "calprinter.h"
#endif
#include "koglobals.h"
#include "koprefs.h"
#include "koeventviewerdialog.h"

#include "kowhatsnextview.h"
using namespace KOrg;
#include "kowhatsnextview.moc"

void WhatsNextTextBrowser::setSource(const QString& n)
{
  kdDebug() << "WhatsNextTextBrowser::setSource(): " << n << endl;

  if (n.startsWith("event:")) {
    emit showIncidence(n);
    return;
  } else if (n.startsWith("todo:")) {
    emit showIncidence(n);
    return;
  } else {
    QTextBrowser::setSource(n);
  }
}

KOWhatsNextView::KOWhatsNextView(Calendar *calendar, QWidget *parent,
                                 const char *name)
  : KOrg::BaseView(calendar, parent, name)
{
  QLabel *dateLabel =
      new QLabel(KGlobal::locale()->formatDate(QDate::currentDate()),this);
  dateLabel->setMargin(2);
  dateLabel->setAlignment(AlignCenter);

  mView = new WhatsNextTextBrowser(this);
  connect(mView,SIGNAL(showIncidence(const QString &)),SLOT(showIncidence(const QString &)));

  mEventViewer = 0;

  QBoxLayout *topLayout = new QVBoxLayout(this);
  topLayout->addWidget(dateLabel);
  topLayout->addWidget(mView);
}

KOWhatsNextView::~KOWhatsNextView()
{
}

int KOWhatsNextView::maxDatesHint()
{
  return 0;
}

int KOWhatsNextView::currentDateCount()
{
  return 0;
}

QPtrList<Incidence> KOWhatsNextView::selectedIncidences()
{
  QPtrList<Incidence> eventList;

  return eventList;
}

void KOWhatsNextView::printPreview(CalPrinter *calPrinter, const QDate &fd,
                               const QDate &td)
{
#ifndef KORG_NOPRINTER
  calPrinter->preview(CalPrinter::Day, fd, td);
#endif
}

void KOWhatsNextView::updateView()
{
  mText = i18n("
\n");
  mText += i18n("
");
  mText += i18n("
What's next?
");
  mText += i18n("
\n
");

  QPtrList<Event> events = calendar()->getEvents(QDate::currentDate(),
                                                 QDate::currentDate());
  if (events.count() > 0) {
    mText += i18n("

Events:
\n");
    mText += i18n("
\n");
    Event *ev = events.first();
    while(ev) {
      if (!ev->recurrence()->doesRecur() || ev->recursOn( QDate::currentDate())) {
        appendEvent(ev);
      }
      ev = events.next();
    }
    mText += i18n("
\n");
  }

  events = calendar()->getEvents(QDate::currentDate(), QDate(2975,12,6));
  if (events.count() > 0) {
    int replys = 0;
    Event *ev = events.first();
    while(ev) {
      Attendee *me = ev->attendeeByMails(KOPrefs::instance()->mAdditionalMails,KOPrefs::instance()->email());
      if (me!=0) {
        if (me->status()==Attendee::NeedsAction && me->RSVP()) {
          if (replys == 0) {
            mText += i18n("

Events that need a reply:
\n");
            mText += i18n("
\n");
          }
          replys++;
          appendEvent(ev,true);
        }
      }
      ev = events.next();
    }
    if (replys > 0 ) mText += i18n("
\n");
  }

  QPtrList<Todo> todos = calendar()->getTodoList();
  if (todos.count() > 0) {
    mText += i18n("
To-Do:
\n");
    mText += i18n("
\n");
    Todo *todo = todos.first();
    while(todo) {
      if (!todo->isCompleted() && (todo->priority() == 1 ||
          (todo->hasDueDate() && todo->dtDue().date() == QDate::currentDate())))
        appendTodo(todo);
      todo = todos.next();
    }
    mText += i18n("
\n");
  }

  mText += i18n("
\n
\n");

  kdDebug() << "KOWhatsNextView::updateView: text: " << mText << endl;
  mView->setText(mText);
}

void KOWhatsNextView::showDates(const QDate &, const QDate &)
{
  updateView();
}

void KOWhatsNextView::showEvents(QPtrList<Event>)
{
}

void KOWhatsNextView::changeEventDisplay(Event *, int action)
{
  switch(action) {
    case KOGlobals::EVENTADDED:
      break;
    case KOGlobals::EVENTEDITED:
      break;
    case KOGlobals::EVENTDELETED:
      break;
    default:
      kdDebug() << "KOWhatsNextView::changeEventDisplay(): Illegal action " << action << endl;
  }
}

void KOWhatsNextView::appendEvent(Event *ev, bool reply)
{
  kdDebug() << "KOWhatsNextView::appendEvent(): " << ev->uid() << endl;

  mText += "
";
  if (!ev->doesFloat()) {
    if (reply) mText += "on " + ev->dtStartDateStr() + ": ";
    mText += ev->dtStartTimeStr() + " - " + ev->dtEndTimeStr();
  }
  mText += "	uid() + "\">";
  mText += ev->summary();
  mText += "
\n";
}

void KOWhatsNextView::appendTodo(Todo *ev)
{
  mText += "
uid() + "\">";
  mText += ev->summary();
  mText += "
\n";
}

void KOWhatsNextView::createEventViewer()
{
  if (!mEventViewer) {
    mEventViewer = new KOEventViewerDialog(this);
  }
}

// TODO: Create this function in CalendarView and remove it from here
void KOWhatsNextView::showIncidence(const QString &uid)
{
  kdDebug() << "KOWhatsNextView::showIncidence(): " << uid << endl;

  if (uid.startsWith("event://")) {
    Event *event = calendar()->getEvent(uid.mid(8));
    if (!event) return;
    createEventViewer();
    mEventViewer->setEvent(event);
  } else if (uid.startsWith("todo://")) {
    Todo *todo = calendar()->getTodo(uid.mid(7));
    if (!todo) return;
    createEventViewer();
    mEventViewer->setTodo(todo);
  }
  mEventViewer->show();
  mEventViewer->raise();
}
<commit_msg>some eyecandy<commit_after>/*
    This file is part of KOrganizer.
    Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

// $Id$

#include <qlayout.h>
#include <qtextbrowser.h>
#include <qtextcodec.h>
#include <qfileinfo.h>
#include <qlabel.h>

#include <kglobal.h>
#include <klocale.h>
#include <kdebug.h>
#include <kiconloader.h>
#include <kmessagebox.h>

#include <libkcal/calendar.h>

#ifndef KORG_NOPRINTER
#include "calprinter.h"
#endif
#include "koglobals.h"
#include "koprefs.h"
#include "koeventviewerdialog.h"

#include "kowhatsnextview.h"
using namespace KOrg;
#include "kowhatsnextview.moc"

void WhatsNextTextBrowser::setSource(const QString& n)
{
  kdDebug() << "WhatsNextTextBrowser::setSource(): " << n << endl;

  if (n.startsWith("event:")) {
    emit showIncidence(n);
    return;
  } else if (n.startsWith("todo:")) {
    emit showIncidence(n);
    return;
  } else {
    QTextBrowser::setSource(n);
  }
}

KOWhatsNextView::KOWhatsNextView(Calendar *calendar, QWidget *parent,
                                 const char *name)
  : KOrg::BaseView(calendar, parent, name)
{
  QLabel *dateLabel =
      new QLabel(KGlobal::locale()->formatDate(QDate::currentDate()),this);
  dateLabel->setMargin(2);
  dateLabel->setAlignment(AlignCenter);

  mView = new WhatsNextTextBrowser(this);
  connect(mView,SIGNAL(showIncidence(const QString &)),SLOT(showIncidence(const QString &)));

  mEventViewer = 0;

  QBoxLayout *topLayout = new QVBoxLayout(this);
  topLayout->addWidget(dateLabel);
  topLayout->addWidget(mView);
}

KOWhatsNextView::~KOWhatsNextView()
{
}

int KOWhatsNextView::maxDatesHint()
{
  return 0;
}

int KOWhatsNextView::currentDateCount()
{
  return 0;
}

QPtrList<Incidence> KOWhatsNextView::selectedIncidences()
{
  QPtrList<Incidence> eventList;

  return eventList;
}

void KOWhatsNextView::printPreview(CalPrinter *calPrinter, const QDate &fd,
                               const QDate &td)
{
#ifndef KORG_NOPRINTER
  calPrinter->preview(CalPrinter::Day, fd, td);
#endif
}

void KOWhatsNextView::updateView()
{
  KIconLoader kil("korganizer");
  QString *ipath = new QString();
  kil.loadIcon("korganizer",KIcon::NoGroup,32,KIcon::DefaultState,ipath);

  mText = i18n("
\n");
  mText += i18n("

");
  mText += i18n("");
  mText += i18n(" What's next?
");
  mText += i18n("
\n
");

  QPtrList<Event> events = calendar()->getEvents(QDate::currentDate(),
                                                 QDate::currentDate());
  if (events.count() > 0) {
    mText += i18n("

");
    kil.loadIcon("appointment",KIcon::NoGroup,22,KIcon::DefaultState,ipath);
    mText += i18n("
");
    mText += i18n("Events:
\n");
    mText += i18n("
\n");
    Event *ev = events.first();
    while(ev) {
      if (!ev->recurrence()->doesRecur() || ev->recursOn( QDate::currentDate())) {
        appendEvent(ev);
      }
      ev = events.next();
    }
    mText += i18n("
\n");
  }

  events = calendar()->getEvents(QDate::currentDate(), QDate(2975,12,6));
  if (events.count() > 0) {
    int replys = 0;
    Event *ev = events.first();
    while(ev) {
      Attendee *me = ev->attendeeByMails(KOPrefs::instance()->mAdditionalMails,KOPrefs::instance()->email());
      if (me!=0) {
        if (me->status()==Attendee::NeedsAction && me->RSVP()) {
          if (replys == 0) {
            mText += i18n("

");
            kil.loadIcon("reply",KIcon::NoGroup,22,KIcon::DefaultState,ipath);
            mText += i18n("
");
            mText += i18n("Events that need a reply:
\n");
            mText += i18n("
\n");
          }
          replys++;
          appendEvent(ev,true);
        }
      }
      ev = events.next();
    }
    if (replys > 0 ) mText += i18n("
\n");
  }

  QPtrList<Todo> todos = calendar()->getTodoList();
  if (todos.count() > 0) {
    kil.loadIcon("todo",KIcon::NoGroup,22,KIcon::DefaultState,ipath);
    mText += i18n("
");
    mText += i18n("To-Do:
\n");
    mText += i18n("
\n");
    Todo *todo = todos.first();
    while(todo) {
      if (!todo->isCompleted() && (todo->priority() == 1 ||
          (todo->hasDueDate() && todo->dtDue().date() == QDate::currentDate())))
        appendTodo(todo);
      todo = todos.next();
    }
    mText += i18n("
\n");
  }

  mText += i18n("
\n
\n");

  kdDebug() << "KOWhatsNextView::updateView: text: " << mText << endl;
  mView->setText(mText);
}

void KOWhatsNextView::showDates(const QDate &, const QDate &)
{
  updateView();
}

void KOWhatsNextView::showEvents(QPtrList<Event>)
{
}

void KOWhatsNextView::changeEventDisplay(Event *, int action)
{
  switch(action) {
    case KOGlobals::EVENTADDED:
      break;
    case KOGlobals::EVENTEDITED:
      break;
    case KOGlobals::EVENTDELETED:
      break;
    default:
      kdDebug() << "KOWhatsNextView::changeEventDisplay(): Illegal action " << action << endl;
  }
}

void KOWhatsNextView::appendEvent(Event *ev, bool reply)
{
  kdDebug() << "KOWhatsNextView::appendEvent(): " << ev->uid() << endl;

  mText += "
";
  if (!ev->doesFloat()) {
    if (reply) mText += "on " + ev->dtStartDateStr() + ": ";
    mText += ev->dtStartTimeStr() + " - " + ev->dtEndTimeStr();
  }
  mText += "	uid() + "\">";
  mText += ev->summary();
  mText += "
\n";
}

void KOWhatsNextView::appendTodo(Todo *ev)
{
  mText += "
uid() + "\">";
  mText += ev->summary();
  mText += "
\n";
}

void KOWhatsNextView::createEventViewer()
{
  if (!mEventViewer) {
    mEventViewer = new KOEventViewerDialog(this);
  }
}

// TODO: Create this function in CalendarView and remove it from here
void KOWhatsNextView::showIncidence(const QString &uid)
{
  kdDebug() << "KOWhatsNextView::showIncidence(): " << uid << endl;

  if (uid.startsWith("event://")) {
    Event *event = calendar()->getEvent(uid.mid(8));
    if (!event) return;
    createEventViewer();
    mEventViewer->setEvent(event);
  } else if (uid.startsWith("todo://")) {
    Todo *todo = calendar()->getTodo(uid.mid(7));
    if (!todo) return;
    createEventViewer();
    mEventViewer->setTodo(todo);
  }
  mEventViewer->show();
  mEventViewer->raise();
}
<|endoftext|>


<commit_before>#include "ksp_plugin/rendering_frame.hpp"

#include "geometry/rotation.hpp"
#include "ksp_plugin/celestial.hpp"
#include "physics/transforms.hpp"
#include "quantities/quantities.hpp"

using principia::quantities::Angle;
using principia::quantities::ArcTan;
using principia::quantities::Time;
using principia::geometry::Displacement;
using principia::geometry::InnerProduct;
using principia::geometry::Rotation;
using principia::geometry::Wedge;
using principia::physics::BodyCentredNonRotatingTransformingIterator;

namespace principia {
namespace ksp_plugin {

namespace {

// Returns an iterator for the first entry in |trajectory| with a time greater
// than or equal to |t|.
// TODO(phl): This is O(N), so we might want to expose a more efficient version.
// But then it's likely that we'll just rewrite this class anyway.
Trajectory<Barycentre>::NativeIterator LowerBound(
    Instant const& t, Trajectory<Barycentre> const& trajectory) {
  for (Trajectory<Barycentre>::NativeIterator it = trajectory.first();
       !it.at_end();
       ++it) {
    if (it.time() >= t) {
      return it;
    }
  }
  LOG(FATAL) << t << " not found in trajectory";
  return trajectory.first();
}

}  // namespace

BodyCentredNonRotatingFrame::BodyCentredNonRotatingFrame(
    Celestial<Barycentre> const& body) : body_(body) {}

std::unique_ptr<Trajectory<Barycentre>>
BodyCentredNonRotatingFrame::ApparentTrajectory(
    Trajectory<Barycentre> const& actual_trajectory) const {
  std::unique_ptr<Trajectory<Barycentre>> result =
      std::make_unique<Trajectory<Barycentre>>(actual_trajectory.body());
  // TODO(phl): Should tag the two frames differently.
  auto it =
      BodyCentredNonRotatingTransformingIterator<Barycentre, Barycentre>(
          body_.prolongation(), &actual_trajectory);
  for (; !it.at_end(); ++it) {
    result->Append(it.time(), it.degrees_of_freedom());
  }
  return std::move(result);
}

BarycentricRotatingFrame::BarycentricRotatingFrame(
    Celestial<Barycentre> const& primary,
    Celestial<Barycentre> const& secondary)
    : primary_(primary),
      secondary_(secondary) {}

std::unique_ptr<Trajectory<Barycentre>>
BarycentricRotatingFrame::ApparentTrajectory(
    Trajectory<Barycentre> const& actual_trajectory) const {
  std::unique_ptr<Trajectory<Barycentre>> result =
      std::make_unique<Trajectory<Barycentre>>(actual_trajectory.body());
  Trajectory<Barycentre>::NativeIterator actual_it = actual_trajectory.first();
  Trajectory<Barycentre>::NativeIterator primary_it =
      LowerBound(actual_it.time(), primary_.history());
  Trajectory<Barycentre>::NativeIterator secondary_it =
      LowerBound(actual_it.time(), secondary_.history());
  DegreesOfFreedom<Barycentre> const& current_primary_state =
      primary_.prolongation().last().degrees_of_freedom();
  DegreesOfFreedom<Barycentre> const& current_secondary_state =
      secondary_.prolongation().last().degrees_of_freedom();
  Position<Barycentre> const current_barycentre =
      geometry::Barycentre<Displacement<Barycentre>, Mass>(
          {current_primary_state.position, current_secondary_state.position},
          {primary_.body().mass(), secondary_.body().mass()});
  Displacement<Barycentre> const to =
        current_primary_state.position - current_barycentre;
  for (; !actual_it.at_end(); ++actual_it) {
    Instant const& t = actual_it.time();
    DegreesOfFreedom<Barycentre> const& actual_state =
        actual_it.degrees_of_freedom();
    while (primary_it.time() < t) {
      ++primary_it;
      ++secondary_it;
    }
    if (primary_it.time() == t) {
      DegreesOfFreedom<Barycentre> const& primary_state =
          primary_it.degrees_of_freedom();
      DegreesOfFreedom<Barycentre> const& secondary_state =
          secondary_it.degrees_of_freedom();
      Position<Barycentre> const barycentre =
          geometry::Barycentre<Displacement<Barycentre>, Mass>(
              {primary_state.position, secondary_state.position},
              {primary_.body().mass(), secondary_.body().mass()});

      Displacement<Barycentre> const from = primary_state.position - barycentre;
      auto const wedge = Wedge(from, to);
      auto const inverse_product_of_norms = 1 / (from.Norm() * to.Norm());
      Angle const angle =
          ArcTan(wedge.Norm() * inverse_product_of_norms,
                 InnerProduct(from, to) * inverse_product_of_norms);
      Rotation<Barycentre, Barycentre> const rotation =
          Rotation<Barycentre, Barycentre>(angle, wedge);
      VLOG(1) << "Rotation :\n"
              << "from     : " << from << "\n"
              << "to       : " << to << "\n"
              << "wedge    : " << wedge << "\n"
              << "angle    : " << angle  << "\n"
              << "rotation : " << rotation;
      // TODO(egg): We should have a vector space structure on
      // |DegreesOfFreedom<Fries>|.
      result->Append(t,
                     {rotation(actual_state.position - barycentre) +
                          current_barycentre,
                      // This would not be trivial to compute, but we don't use
                      // it...
                      actual_state.velocity});
    }
  }
  return std::move(result);
}

}  // namespace ksp_plugin
}  // namespace principia
<commit_msg>I cannot into numericz<commit_after>#include "ksp_plugin/rendering_frame.hpp"

#include "geometry/rotation.hpp"
#include "ksp_plugin/celestial.hpp"
#include "physics/transforms.hpp"
#include "quantities/quantities.hpp"

using principia::quantities::Angle;
using principia::quantities::ArcTan;
using principia::quantities::Time;
using principia::geometry::Displacement;
using principia::geometry::InnerProduct;
using principia::geometry::Rotation;
using principia::geometry::Wedge;
using principia::physics::BodyCentredNonRotatingTransformingIterator;

namespace principia {
namespace ksp_plugin {

namespace {

// Returns an iterator for the first entry in |trajectory| with a time greater
// than or equal to |t|.
// TODO(phl): This is O(N), so we might want to expose a more efficient version.
// But then it's likely that we'll just rewrite this class anyway.
Trajectory<Barycentre>::NativeIterator LowerBound(
    Instant const& t, Trajectory<Barycentre> const& trajectory) {
  for (Trajectory<Barycentre>::NativeIterator it = trajectory.first();
       !it.at_end();
       ++it) {
    if (it.time() >= t) {
      return it;
    }
  }
  LOG(FATAL) << t << " not found in trajectory";
  return trajectory.first();
}

}  // namespace

BodyCentredNonRotatingFrame::BodyCentredNonRotatingFrame(
    Celestial<Barycentre> const& body) : body_(body) {}

std::unique_ptr<Trajectory<Barycentre>>
BodyCentredNonRotatingFrame::ApparentTrajectory(
    Trajectory<Barycentre> const& actual_trajectory) const {
  std::unique_ptr<Trajectory<Barycentre>> result =
      std::make_unique<Trajectory<Barycentre>>(actual_trajectory.body());
  // TODO(phl): Should tag the two frames differently.
  auto it =
      BodyCentredNonRotatingTransformingIterator<Barycentre, Barycentre>(
          body_.prolongation(), &actual_trajectory);
  for (; !it.at_end(); ++it) {
    result->Append(it.time(), it.degrees_of_freedom());
  }
  return std::move(result);
}

BarycentricRotatingFrame::BarycentricRotatingFrame(
    Celestial<Barycentre> const& primary,
    Celestial<Barycentre> const& secondary)
    : primary_(primary),
      secondary_(secondary) {}

std::unique_ptr<Trajectory<Barycentre>>
BarycentricRotatingFrame::ApparentTrajectory(
    Trajectory<Barycentre> const& actual_trajectory) const {
  std::unique_ptr<Trajectory<Barycentre>> result =
      std::make_unique<Trajectory<Barycentre>>(actual_trajectory.body());
  Trajectory<Barycentre>::NativeIterator actual_it = actual_trajectory.first();
  Trajectory<Barycentre>::NativeIterator primary_it =
      LowerBound(actual_it.time(), primary_.history());
  Trajectory<Barycentre>::NativeIterator secondary_it =
      LowerBound(actual_it.time(), secondary_.history());
  DegreesOfFreedom<Barycentre> const& current_primary_state =
      primary_.prolongation().last().degrees_of_freedom();
  DegreesOfFreedom<Barycentre> const& current_secondary_state =
      secondary_.prolongation().last().degrees_of_freedom();
  Position<Barycentre> const current_barycentre =
      geometry::Barycentre<Displacement<Barycentre>, Mass>(
          {current_primary_state.position, current_secondary_state.position},
          {primary_.body().mass(), secondary_.body().mass()});
  Displacement<Barycentre> const to =
        current_primary_state.position - current_barycentre;
  for (; !actual_it.at_end(); ++actual_it) {
    Instant const& t = actual_it.time();
    DegreesOfFreedom<Barycentre> const& actual_state =
        actual_it.degrees_of_freedom();
    while (primary_it.time() < t) {
      ++primary_it;
      ++secondary_it;
    }
    if (primary_it.time() == t) {
      DegreesOfFreedom<Barycentre> const& primary_state =
          primary_it.degrees_of_freedom();
      DegreesOfFreedom<Barycentre> const& secondary_state =
          secondary_it.degrees_of_freedom();
      Position<Barycentre> const barycentre =
          geometry::Barycentre<Displacement<Barycentre>, Mass>(
              {primary_state.position, secondary_state.position},
              {primary_.body().mass(), secondary_.body().mass()});

      Displacement<Barycentre> const from = primary_state.position - barycentre;
      auto const wedge = Wedge(from, to);
      Angle const angle = ArcTan(wedge.Norm(), InnerProduct(from, to));
      Rotation<Barycentre, Barycentre> const rotation =
          Rotation<Barycentre, Barycentre>(angle, wedge);
      VLOG(1) << "Rotation :\n"
              << "from     : " << from << "\n"
              << "to       : " << to << "\n"
              << "wedge    : " << wedge << "\n"
              << "angle    : " << angle  << "\n"
              << "rotation : " << rotation;
      // TODO(egg): We should have a vector space structure on
      // |DegreesOfFreedom<Fries>|.
      result->Append(t,
                     {rotation(actual_state.position - barycentre) +
                          current_barycentre,
                      // This would not be trivial to compute, but we don't use
                      // it...
                      actual_state.velocity});
    }
  }
  return std::move(result);
}

}  // namespace ksp_plugin
}  // namespace principia
<|endoftext|>


<commit_before>/*
 * api.cpp
 *
 *  Created on: 2016年12月16日
 *      Author: zhuqian
 */
#include "api.h"
#include "transform.h"
//transform相关参数
constexpr int MaxTransforms = 2;
constexpr int StartTransformBits = 1 << 0;	//0x01
constexpr int EndTransformBits = 1 << 1;	//0x10
constexpr int AllTransformsBits = (1 << MaxTransforms) - 1;	//0x11
//transform集合
struct TransformSet {
private:
	Transform _t[MaxTransforms];
public:
	Transform& operator[](int i) {
		Assert(i >= 0 && i < MaxTransforms);
		return _t[i];
	}
	const Transform& operator[](int i) const {
		Assert(i >= 0 && i < MaxTransforms);
		return _t[i];
	}
	//判断是否包含不同的transform
	bool IsAnimated() const{
		for(int i=0;i<MaxTransforms-1;++i){
			if(_t[i]!=_t[i+1]){
				return true;
			}
		}
		return false;
	}
	//返回transformSet的逆
	friend TransformSet Inverse(const TransformSet& ts){
		TransformSet invSet;
		for(int i=0;i<MaxTransforms;++i){
			invSet._t[i]=Inverse(ts._t[i]);
		}
		return invSet;
	}
};

<commit_msg>add RenderOptions<commit_after>/*
 * api.cpp
 *
 *  Created on: 2016年12月16日
 *      Author: zhuqian
 */
#include "api.h"
#include "transform.h"
#include "paramset.h"
//transform相关参数
constexpr int MaxTransforms = 2;
constexpr int StartTransformBits = 1 << 0;	//0x01
constexpr int EndTransformBits = 1 << 1;	//0x10
constexpr int AllTransformsBits = (1 << MaxTransforms) - 1;	//0x11
//transform集合
struct TransformSet {
private:
	Transform _t[MaxTransforms];
public:
	Transform& operator[](int i) {
		Assert(i >= 0 && i < MaxTransforms);
		return _t[i];
	}
	const Transform& operator[](int i) const {
		Assert(i >= 0 && i < MaxTransforms);
		return _t[i];
	}
	//判断是否包含不同的transform
	bool IsAnimated() const {
		for (int i = 0; i < MaxTransforms - 1; ++i) {
			if (_t[i] != _t[i + 1]) {
				return true;
			}
		}
		return false;
	}
	//返回transformSet的逆
	friend TransformSet Inverse(const TransformSet& ts) {
		TransformSet invSet;
		for (int i = 0; i < MaxTransforms; ++i) {
			invSet._t[i] = Inverse(ts._t[i]);
		}
		return invSet;
	}
};
//渲染参数
struct RenderOptions {
	Float transformStartTime = 0;
	Float transformEndTime = 1;
	//过滤器名字  默认 box
	std::string FilterName = "box";
	ParamSet FilterParams;
	//Film的名字
	std::string FilmName = "image";
	ParamSet FilmParams;
	//采样器的名字
	std::string SamplerName = "random";
	ParamSet SamplerParams;
	//加速结构的名字
	std::string AcceleratorName = "normal";
	ParamSet AcceleratorParams;
	//积分器的名字
	std::string IntegratorName = "normal";
	ParamSet IntegratorParams;
	//相机的名字
	std::string CameraName = "pinhole";
	ParamSet CameraParams;
	//光源
	std::vector<std::shared_ptr<Light>> lights;
	//图元
	std::vector<std::shared_ptr<Primitive>> primitives;
};
<|endoftext|>


<commit_before>#include <stdio.h>

#include <ros/ros.h>
#include <webrtc/base/ssladapter.h>
#include <webrtc/system_wrappers/include/trace.h>

#include "config.h"
#include "host.h"

#include <malloc.h>
#include <sys/resource.h>

struct Flush {

    Flush(Host& host) : host(host) {}

    void operator()(const ros::TimerEvent& event) {
        if (!ros::isShuttingDown()) {
            auto stats = host.flush();
            if (stats.reaped_data_messages) {
                ROS_INFO(
                    "flushed - reaped_data_messages=%zu",
                    stats.reaped_data_messages
                );
            }
        }
    }

    Host &host;

};

struct Reap {

    Reap(Host& host, double stale_threhold=30)
        : host(host),
          stale_threhold(stale_threhold) {
    }

    void operator()(const ros::TimerEvent& event) {
        if (!ros::isShuttingDown()) {
            auto stats = host.reap(stale_threhold);
            if (stats.deleted_connections) {
                ROS_INFO(
                    "reaped - deleted_connections=%zu",
                    stats.deleted_connections
                );
            }
        }
    }

    Host &host;
    double stale_threhold;

};

int main(int argc, char **argv) {
    ROS_INFO("initializing ros");
    ros::init(argc, argv, "host");

    ros::NodeHandle nh;

    ROS_INFO("loading config");
    Config config(Config::get(nh));

    if (!config.trace_file.empty()) {
        ROS_INFO(
            "setting webrtc trace file to %s w/ mask 0x%04x",
            config.trace_file.c_str(), config.trace_mask
        );
        webrtc::Trace::set_level_filter(config.trace_mask);
        webrtc::Trace::CreateTrace();
        webrtc::Trace::SetTraceFile(config.trace_file.c_str());
    }

    ROS_INFO("initializing ssl");
    if (!rtc::InitializeSSL()) {
        ROS_ERROR("ssl initialization failed");
        return 1;
    }

    struct rlimit corelimit = {0x70000000,0x70000000};
    if(setrlimit(RLIMIT_CORE,&corelimit) < 0) {
        ROS_ERROR("%s",strerror(errno));
        return 1;
    }
    struct rlimit aslimit = {0xA0000000,0xA0000000};
    if(setrlimit(RLIMIT_AS,&corelimit) < 0) {
        ROS_ERROR("%s",strerror(errno));
        return 1;
    }

    ROS_INFO("creating host");
    HostFactory host_factory;
    host_factory.audio_src = config.microphone;
    for (size_t i = 0; i != config.cameras.size(); i++) {
        host_factory.video_srcs.push_back(config.cameras[i]);
    }
    for (size_t i = 0; i != config.ice_servers.size(); i++) {
        host_factory.ice_servers.push_back(config.ice_servers[i]);
    }
    host_factory.pc_constraints = config.pc_constraints;
    host_factory.pc_bond_connect_timeout = config.pc_bond_connect_timeout;
    host_factory.pc_bond_heartbeat_timeout = config.pc_bond_heartbeat_timeout;
    host_factory.queue_sizes = config.queue_sizes;
    Host host = host_factory(nh);

    ROS_INFO("opening host ... ");
    if (!host.open(config.open_media_sources)) {
        ROS_INFO("host open failed");
        return 2;
    }
    ROS_INFO("opened host");

    Flush flush(host);
    ros::Timer flush_timer = nh.createTimer(
        ros::Duration(config.flush_frequency), flush
    );
    if (config.flush_frequency != 0) {
        ROS_INFO("scheduling host flush every %0.1f sec(s) ... ", config.flush_frequency);
        flush_timer.start();
    }

    Reap reap(host);
    ros::Timer reap_timer = nh.createTimer(
        ros::Duration(config.reap_frequency), reap
    );
    if (config.reap_frequency != 0) {
        ROS_INFO("scheduling host reap every %0.1f sec(s) ... ", config.reap_frequency);
        reap_timer.start();
    }

    ROS_INFO("start spinning");
    ros::spin();
    ROS_INFO("stop spinning");

    ROS_INFO("closing host ...");
    host.close();
    ROS_INFO("closed host");

    if (!config.trace_file.empty()) {
        ROS_INFO("resetting webrtc trace file");
        webrtc::Trace::SetTraceFile(NULL);
        webrtc::Trace::ReturnTrace();
    }

    return 0;
}
<commit_msg>PM-2187, rework the safety process to use /proc/PID/oom_score, which tracks RSS instead Still kills a malloc leak before system OOM<commit_after>#include <stdio.h>

#include <ros/ros.h>
#include <webrtc/base/ssladapter.h>
#include <webrtc/system_wrappers/include/trace.h>

#include "config.h"
#include "host.h"

#include <malloc.h>
#include <sys/resource.h>
#include <stdio.h>

struct Flush {

    Flush(Host& host) : host(host) {}

    void operator()(const ros::TimerEvent& event) {
        if (!ros::isShuttingDown()) {
            auto stats = host.flush();
            if (stats.reaped_data_messages) {
                ROS_INFO(
                    "flushed - reaped_data_messages=%zu",
                    stats.reaped_data_messages
                );
            }
        }
    }

    Host &host;

};

struct Reap {

    Reap(Host& host, double stale_threhold=30)
        : host(host),
          stale_threhold(stale_threhold) {
    }

    void operator()(const ros::TimerEvent& event) {
        if (!ros::isShuttingDown()) {
            auto stats = host.reap(stale_threhold);
            if (stats.deleted_connections) {
                ROS_INFO(
                    "reaped - deleted_connections=%zu",
                    stats.deleted_connections
                );
            }
            // After reaping, check our OOM score to
            //  see if we are running away with memory
            static FILE* proc_file;
            if(!proc_file) {
                char proc_path[128];
                int pidnum = (int)getpid();
                snprintf(proc_path,sizeof(proc_path)-1,
                         "/proc/%d/oom_score",pidnum);
                proc_file = fopen(proc_path,"r");
            }
            rewind(proc_file);
            int oom_score;
            fscanf(proc_file,"%d",&oom_score);
            if(oom_score > 400) {
                ROS_INFO(
                    "Memory went over limit (%d percent)",oom_score/10
                );
                abort();
            }
        }
    }

    Host &host;
    double stale_threhold;

};

int main(int argc, char **argv) {
    ROS_INFO("initializing ros");
    ros::init(argc, argv, "host");

    ros::NodeHandle nh;

    ROS_INFO("loading config");
    Config config(Config::get(nh));

    if (!config.trace_file.empty()) {
        ROS_INFO(
            "setting webrtc trace file to %s w/ mask 0x%04x",
            config.trace_file.c_str(), config.trace_mask
        );
        webrtc::Trace::set_level_filter(config.trace_mask);
        webrtc::Trace::CreateTrace();
        webrtc::Trace::SetTraceFile(config.trace_file.c_str());
    }

    ROS_INFO("initializing ssl");
    if (!rtc::InitializeSSL()) {
        ROS_ERROR("ssl initialization failed");
        return 1;
    }

    struct rlimit corelimit = {0x70000000,0x70000000};
    if(setrlimit(RLIMIT_CORE,&corelimit) < 0) {
        ROS_ERROR("%s",strerror(errno));
        return 1;
    }
    struct rlimit aslimit = {0xA0000000,0xA0000000};
    if(setrlimit(RLIMIT_AS,&corelimit) < 0) {
        ROS_ERROR("%s",strerror(errno));
        return 1;
    }

    ROS_INFO("creating host");
    HostFactory host_factory;
    host_factory.audio_src = config.microphone;
    for (size_t i = 0; i != config.cameras.size(); i++) {
        host_factory.video_srcs.push_back(config.cameras[i]);
    }
    for (size_t i = 0; i != config.ice_servers.size(); i++) {
        host_factory.ice_servers.push_back(config.ice_servers[i]);
    }
    host_factory.pc_constraints = config.pc_constraints;
    host_factory.pc_bond_connect_timeout = config.pc_bond_connect_timeout;
    host_factory.pc_bond_heartbeat_timeout = config.pc_bond_heartbeat_timeout;
    host_factory.queue_sizes = config.queue_sizes;
    Host host = host_factory(nh);

    ROS_INFO("opening host ... ");
    if (!host.open(config.open_media_sources)) {
        ROS_INFO("host open failed");
        return 2;
    }
    ROS_INFO("opened host");

    Flush flush(host);
    ros::Timer flush_timer = nh.createTimer(
        ros::Duration(config.flush_frequency), flush
    );
    if (config.flush_frequency != 0) {
        ROS_INFO("scheduling host flush every %0.1f sec(s) ... ", config.flush_frequency);
        flush_timer.start();
    }

    Reap reap(host);
    ros::Timer reap_timer = nh.createTimer(
        ros::Duration(config.reap_frequency), reap
    );
    if (config.reap_frequency != 0) {
        ROS_INFO("scheduling host reap every %0.1f sec(s) ... ", config.reap_frequency);
        reap_timer.start();
    }

    ROS_INFO("start spinning");
    ros::spin();
    ROS_INFO("stop spinning");

    ROS_INFO("closing host ...");
    host.close();
    ROS_INFO("closed host");

    if (!config.trace_file.empty()) {
        ROS_INFO("resetting webrtc trace file");
        webrtc::Trace::SetTraceFile(NULL);
        webrtc::Trace::ReturnTrace();
    }

    return 0;
}
<|endoftext|>


<commit_before>#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include <limits.h>
#include <string.h>
#include <stdint.h>

//Forward declaration required due to CFFI's requirement to have unmangled symbols
extern "C" {
	int pairwise_diff(const double* a, const double* b, double* result, size_t awidth, size_t bwidth);
}

int pairwise_diff(const double* a, const double* b, double* result, size_t awidth, size_t bwidth) {

	//Iterate over all (a,b) element pairs
	for (size_t ax = 0; ax < awidth; ++ax) {
		for (size_t bx = 0; bx < bwidth; ++bx) {
			result[ax*awidth + bx] = abs(a[ax] - b[bx]);
		}
	}
	return 0;
}
<commit_msg>Try to avoid ambiguous abs() call in distance.cpp by explicit cast to int64_t (in an attempt to resolve #1)<commit_after>#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include <limits.h>
#include <string.h>
#include <stdint.h>

//Forward declaration required due to CFFI's requirement to have unmangled symbols
extern "C" {
	int pairwise_diff(const double* a, const double* b, double* result, size_t awidth, size_t bwidth);
}

int pairwise_diff(const double* a, const double* b, double* result, size_t awidth, size_t bwidth) {

	//Iterate over all (a,b) element pairs
	for (size_t ax = 0; ax < awidth; ++ax) {
		for (size_t bx = 0; bx < bwidth; ++bx) {
			result[ax*awidth + bx] = abs((int64_t)(a[ax] - b[bx]));
		}
	}
	return 0;
}
<|endoftext|>