<commit_before>#include <iostream>
#include <algorithm>

#include <unistd.h>
#include <fcntl.h>

#include "dasync.h"

#include "service.h"
#include "dinit-log.h"
#include "cpbuffer.h"

// TODO should disarm, not remove, the file descriptor watchers when they are not busy
//      (and likewise re-arm instead of re-add them when new data arrives).

extern EventLoop_t eventLoop;

LogLevel log_level = LogLevel::WARN;
LogLevel cons_log_level = LogLevel::WARN;

static bool log_to_console = false;   // whether we should output log messages to
                                     // console immediately
static bool log_current_line;  // Whether the current line is being logged

static ServiceSet *service_set = nullptr;  // Reference to service set

namespace {
class BufferedLogStream : public PosixFdWatcher<NullMutex>
{
    private:

    // Outgoing:
    bool partway = false;     // if we are partway throught output of a log message
    bool discarded = false;   // if we have discarded a message

    // A "special message" is not stored in the circular buffer; instead
    // it is delivered from an external buffer not managed by BufferedLogger.
    bool special = false;      // currently outputting special message?
    char *special_buf; // buffer containing special message
    int msg_index;     // index into special message

    public:
    CPBuffer<4096> log_buffer;

    // Incoming:
    int current_index = 0;    // current/next incoming message index
       // ^^ TODO is this always just the length of log_buffer?

    int fd;

    void init(int fd)
    {
        this->fd = fd;
    }

    Rearm gotEvent(EventLoop_t *loop, int fd, int flags) noexcept override;

    // Check whether the console can be released.
    void flushForRelease();
};
}

// Two log streams:
// (One for main log, one for console)
static BufferedLogStream log_stream[2];

constexpr static int DLOG_MAIN = 0; // main log facility
constexpr static int DLOG_CONS = 1; // console

static void release_console()
{
    if (! log_to_console) {
        int flags = fcntl(1, F_GETFL, 0);
        fcntl(1, F_SETFL, flags & ~O_NONBLOCK);
        service_set->pullConsoleQueue();
    }
}

void BufferedLogStream::flushForRelease()
{
    // Try to flush any messages that are currently buffered. (Console is non-blocking
    // so it will fail gracefully).
    if (gotEvent(&eventLoop, fd, out_events) == Rearm::REMOVE) {
        // Console has already been released at this point.
        deregisterWatch(&eventLoop);
    }
    // gotEvent didn't want to disarm, so must be partway through a message; will
    // release when it's finished.
}

Rearm BufferedLogStream::gotEvent(EventLoop_t *loop, int fd, int flags) noexcept
{
    // TODO correct for the case that this is *not* the console log stream.

    auto &log_stream = *this;

    if ((! partway) && log_stream.special) {
        char * start = log_stream.special_buf + log_stream.msg_index;
        char * end = std::find(log_stream.special_buf + log_stream.msg_index, (char *)nullptr, '\n');
        int r = write(fd, start, end - start + 1);
        if (r >= 0) {
            if (start + r > end) {
                // All written: go on to next message in queue
                log_stream.special = false;
                log_stream.partway = false;
                log_stream.msg_index = 0;

                if (!log_to_console) {
                    release_console();
                    return Rearm::REMOVE;
                }
            }
            else {
                log_stream.msg_index += r;
                return Rearm::REARM;
            }
        }
        else {
            // spurious readiness - EAGAIN or EWOULDBLOCK?
            // other error?
            // TODO
        }
        return Rearm::REARM;
    }
    else {
        // Writing from the regular circular buffer

        // TODO issue special message if we have discarded a log message

        if (log_stream.current_index == 0) {
            release_console();
            return Rearm::REMOVE;
        }

        char *ptr = log_stream.log_buffer.get_ptr(0);
        int len = log_stream.log_buffer.get_contiguous_length(ptr);
        char *creptr = ptr + len;  // contiguous region end
        char *eptr = std::find(ptr, creptr, '\n');

        bool will_complete = false;  // will complete this message?
        if (eptr != creptr) {
            eptr++;  // include '\n'
            will_complete = true;
        }

        len = eptr - ptr;

        int r = write(fd, ptr, len);

        if (r >= 0) {
            bool complete = (r == len) && will_complete;
            log_stream.log_buffer.consume(len);
            log_stream.partway = ! complete;
            if (complete) {
                log_stream.current_index -= len;
                if (log_stream.current_index == 0 || !log_to_console) {
                    // No more messages buffered / stop logging to console:
                    release_console();
                    return Rearm::REMOVE;
                }
            }
        }
        else {
            // TODO
            // EAGAIN / EWOULDBLOCK?
            // error?
            return Rearm::REARM;
        }
    }

    // We've written something by the time we get here. We could fall through to below, but
    // let's give other events a chance to be processed by returning now.
    return Rearm::REARM;
}

void init_log(ServiceSet *sset) noexcept
{
    service_set = sset;
    enable_console_log(true);
}

bool is_log_flushed() noexcept
{
    return log_stream[DLOG_CONS].current_index > 0;
}

// Enable or disable console logging. If disabled, console logging will be disabled on the
// completion of output of the current message (if any), at which point the first service record
// queued in the service set will acquire the console.
void enable_console_log(bool enable) noexcept
{
    if (enable && ! log_to_console) {
        // Console is fd 1 - stdout
        // Set non-blocking IO:
        int flags = fcntl(1, F_GETFL, 0);
        fcntl(1, F_SETFL, flags | O_NONBLOCK);
        // Activate watcher:
        log_stream[DLOG_CONS].init(STDOUT_FILENO);
        if (log_stream[DLOG_CONS].current_index > 0) {
            log_stream[DLOG_CONS].registerWith(&eventLoop, log_stream[DLOG_CONS].fd, out_events);
        }
        log_to_console = true;
    }
    else if (! enable && log_to_console) {
        log_to_console = false;
        log_stream[DLOG_CONS].flushForRelease();
    }
}

// Variadic method to calculate the sum of string lengths:
static int sum_length(const char *arg) noexcept
{
    return std::strlen(arg);
}

template <typename U, typename ... T> static int sum_length(U first, T ... args) noexcept
{
    return sum_length(first) + sum_length(args...);
}

// Variadic method to append strings to a buffer:
static void append(CPBuffer<4096> &buf, const char *s)
{
    buf.append(s, std::strlen(s));
}

template <typename U, typename ... T> static void append(CPBuffer<4096> &buf, U u, T ... t)
{
    append(buf, u);
    append(buf, t...);
}

// Variadic method to log a sequence of strings as a single message:
template <typename ... T> static void do_log(T ... args) noexcept
{
    int amount = sum_length(args...);
    if (log_stream[DLOG_CONS].log_buffer.get_free() >= amount) {
        append(log_stream[DLOG_CONS].log_buffer, args...);

        bool was_first = (log_stream[DLOG_CONS].current_index == 0);
        log_stream[DLOG_CONS].current_index += amount;
        if (was_first && log_to_console) {
            log_stream[DLOG_CONS].registerWith(&eventLoop, log_stream[DLOG_CONS].fd, out_events);
        }
    }
    else {
        // TODO mark a discarded message
    }
}

// Variadic method to potentially log a sequence of strings as a single message with the given log level:
template <typename ... T> static void do_log(LogLevel lvl, T ... args) noexcept
{
    if (lvl >= cons_log_level) {
        do_log(args...);
    }
}

// Log a message. A newline will be appended.
void log(LogLevel lvl, const char *msg) noexcept
{
    do_log(lvl, "dinit: ", msg, "\n");
}

// Log part of a message. A series of calls to do_log_part must be followed by a call to do_log_commit.
template <typename T> static void do_log_part(T arg) noexcept
{
    int amount = sum_length(arg);
    if (log_stream[DLOG_CONS].log_buffer.get_free() >= amount) {
        append(log_stream[DLOG_CONS].log_buffer, arg);
    }
    else {
        // reset
        log_stream[DLOG_CONS].log_buffer.trim_to(log_stream[DLOG_CONS].current_index);
        log_current_line = false;
        // TODO mark discarded message
    }
}

// Commit a message that was issued as a series of parts (via do_log_part).
static void do_log_commit() noexcept
{
    if (log_current_line) {
        bool was_first = log_stream[DLOG_CONS].current_index == 0;
        log_stream[DLOG_CONS].current_index = log_stream[DLOG_CONS].log_buffer.get_length();
        if (was_first && log_to_console) {
            log_stream[DLOG_CONS].registerWith(&eventLoop, log_stream[DLOG_CONS].fd, out_events);
        }
    }
}

// Log a multi-part message beginning
void logMsgBegin(LogLevel lvl, const char *msg) noexcept
{
    // TODO use buffer
    log_current_line = lvl >= log_level;
    if (log_current_line) {
        if (log_to_console) {
            do_log_part("dinit: ");
            do_log_part(msg);
        }
    }
}

// Continue a multi-part log message
void logMsgPart(const char *msg) noexcept
{
    // TODO use buffer
    if (log_current_line) {
        if (log_to_console) {
            do_log_part(msg);
        }
    }
}

// Complete a multi-part log message
void logMsgEnd(const char *msg) noexcept
{
    // TODO use buffer
    if (log_current_line) {
        if (log_to_console) {
            do_log_part(msg);
            do_log_part("\n");
            do_log_commit();
        }
    }
}

void logServiceStarted(const char *service_name) noexcept
{
    do_log("[  OK  ] ", service_name, "\n");
}

void logServiceFailed(const char *service_name) noexcept
{
    do_log("[FAILED] ", service_name, "\n");
}

void logServiceStopped(const char *service_name) noexcept
{
    do_log("[STOPPD] ", service_name, "\n");
}
<commit_msg>Fix condition in is_log_flushed<commit_after>#include <iostream>
#include <algorithm>

#include <unistd.h>
#include <fcntl.h>

#include "dasync.h"

#include "service.h"
#include "dinit-log.h"
#include "cpbuffer.h"

// TODO should disarm, not remove, the file descriptor watchers when they are not busy
//      (and likewise re-arm instead of re-add them when new data arrives).

extern EventLoop_t eventLoop;

LogLevel log_level = LogLevel::WARN;
LogLevel cons_log_level = LogLevel::WARN;

static bool log_to_console = false;   // whether we should output log messages to
                                     // console immediately
static bool log_current_line;  // Whether the current line is being logged

static ServiceSet *service_set = nullptr;  // Reference to service set

namespace {
class BufferedLogStream : public PosixFdWatcher<NullMutex>
{
    private:

    // Outgoing:
    bool partway = false;     // if we are partway throught output of a log message
    bool discarded = false;   // if we have discarded a message

    // A "special message" is not stored in the circular buffer; instead
    // it is delivered from an external buffer not managed by BufferedLogger.
    bool special = false;      // currently outputting special message?
    char *special_buf; // buffer containing special message
    int msg_index;     // index into special message

    public:
    CPBuffer<4096> log_buffer;

    // Incoming:
    int current_index = 0;    // current/next incoming message index
       // ^^ TODO is this always just the length of log_buffer?

    int fd;

    void init(int fd)
    {
        this->fd = fd;
    }

    Rearm gotEvent(EventLoop_t *loop, int fd, int flags) noexcept override;

    // Check whether the console can be released.
    void flushForRelease();
};
}

// Two log streams:
// (One for main log, one for console)
static BufferedLogStream log_stream[2];

constexpr static int DLOG_MAIN = 0; // main log facility
constexpr static int DLOG_CONS = 1; // console

static void release_console()
{
    if (! log_to_console) {
        int flags = fcntl(1, F_GETFL, 0);
        fcntl(1, F_SETFL, flags & ~O_NONBLOCK);
        service_set->pullConsoleQueue();
    }
}

void BufferedLogStream::flushForRelease()
{
    // Try to flush any messages that are currently buffered. (Console is non-blocking
    // so it will fail gracefully).
    if (gotEvent(&eventLoop, fd, out_events) == Rearm::REMOVE) {
        // Console has already been released at this point.
        deregisterWatch(&eventLoop);
    }
    // gotEvent didn't want to disarm, so must be partway through a message; will
    // release when it's finished.
}

Rearm BufferedLogStream::gotEvent(EventLoop_t *loop, int fd, int flags) noexcept
{
    // TODO correct for the case that this is *not* the console log stream.

    auto &log_stream = *this;

    if ((! partway) && log_stream.special) {
        char * start = log_stream.special_buf + log_stream.msg_index;
        char * end = std::find(log_stream.special_buf + log_stream.msg_index, (char *)nullptr, '\n');
        int r = write(fd, start, end - start + 1);
        if (r >= 0) {
            if (start + r > end) {
                // All written: go on to next message in queue
                log_stream.special = false;
                log_stream.partway = false;
                log_stream.msg_index = 0;

                if (!log_to_console) {
                    release_console();
                    return Rearm::REMOVE;
                }
            }
            else {
                log_stream.msg_index += r;
                return Rearm::REARM;
            }
        }
        else {
            // spurious readiness - EAGAIN or EWOULDBLOCK?
            // other error?
            // TODO
        }
        return Rearm::REARM;
    }
    else {
        // Writing from the regular circular buffer

        // TODO issue special message if we have discarded a log message

        if (log_stream.current_index == 0) {
            release_console();
            return Rearm::REMOVE;
        }

        char *ptr = log_stream.log_buffer.get_ptr(0);
        int len = log_stream.log_buffer.get_contiguous_length(ptr);
        char *creptr = ptr + len;  // contiguous region end
        char *eptr = std::find(ptr, creptr, '\n');

        bool will_complete = false;  // will complete this message?
        if (eptr != creptr) {
            eptr++;  // include '\n'
            will_complete = true;
        }

        len = eptr - ptr;

        int r = write(fd, ptr, len);

        if (r >= 0) {
            bool complete = (r == len) && will_complete;
            log_stream.log_buffer.consume(len);
            log_stream.partway = ! complete;
            if (complete) {
                log_stream.current_index -= len;
                if (log_stream.current_index == 0 || !log_to_console) {
                    // No more messages buffered / stop logging to console:
                    release_console();
                    return Rearm::REMOVE;
                }
            }
        }
        else {
            // TODO
            // EAGAIN / EWOULDBLOCK?
            // error?
            return Rearm::REARM;
        }
    }

    // We've written something by the time we get here. We could fall through to below, but
    // let's give other events a chance to be processed by returning now.
    return Rearm::REARM;
}

void init_log(ServiceSet *sset) noexcept
{
    service_set = sset;
    enable_console_log(true);
}

bool is_log_flushed() noexcept
{
    return log_stream[DLOG_CONS].current_index == 0;
}

// Enable or disable console logging. If disabled, console logging will be disabled on the
// completion of output of the current message (if any), at which point the first service record
// queued in the service set will acquire the console.
void enable_console_log(bool enable) noexcept
{
    if (enable && ! log_to_console) {
        // Console is fd 1 - stdout
        // Set non-blocking IO:
        int flags = fcntl(1, F_GETFL, 0);
        fcntl(1, F_SETFL, flags | O_NONBLOCK);
        // Activate watcher:
        log_stream[DLOG_CONS].init(STDOUT_FILENO);
        if (log_stream[DLOG_CONS].current_index > 0) {
            log_stream[DLOG_CONS].registerWith(&eventLoop, log_stream[DLOG_CONS].fd, out_events);
        }
        log_to_console = true;
    }
    else if (! enable && log_to_console) {
        log_to_console = false;
        log_stream[DLOG_CONS].flushForRelease();
    }
}

// Variadic method to calculate the sum of string lengths:
static int sum_length(const char *arg) noexcept
{
    return std::strlen(arg);
}

template <typename U, typename ... T> static int sum_length(U first, T ... args) noexcept
{
    return sum_length(first) + sum_length(args...);
}

// Variadic method to append strings to a buffer:
static void append(CPBuffer<4096> &buf, const char *s)
{
    buf.append(s, std::strlen(s));
}

template <typename U, typename ... T> static void append(CPBuffer<4096> &buf, U u, T ... t)
{
    append(buf, u);
    append(buf, t...);
}

// Variadic method to log a sequence of strings as a single message:
template <typename ... T> static void do_log(T ... args) noexcept
{
    int amount = sum_length(args...);
    if (log_stream[DLOG_CONS].log_buffer.get_free() >= amount) {
        append(log_stream[DLOG_CONS].log_buffer, args...);

        bool was_first = (log_stream[DLOG_CONS].current_index == 0);
        log_stream[DLOG_CONS].current_index += amount;
        if (was_first && log_to_console) {
            log_stream[DLOG_CONS].registerWith(&eventLoop, log_stream[DLOG_CONS].fd, out_events);
        }
    }
    else {
        // TODO mark a discarded message
    }
}

// Variadic method to potentially log a sequence of strings as a single message with the given log level:
template <typename ... T> static void do_log(LogLevel lvl, T ... args) noexcept
{
    if (lvl >= cons_log_level) {
        do_log(args...);
    }
}

// Log a message. A newline will be appended.
void log(LogLevel lvl, const char *msg) noexcept
{
    do_log(lvl, "dinit: ", msg, "\n");
}

// Log part of a message. A series of calls to do_log_part must be followed by a call to do_log_commit.
template <typename T> static void do_log_part(T arg) noexcept
{
    int amount = sum_length(arg);
    if (log_stream[DLOG_CONS].log_buffer.get_free() >= amount) {
        append(log_stream[DLOG_CONS].log_buffer, arg);
    }
    else {
        // reset
        log_stream[DLOG_CONS].log_buffer.trim_to(log_stream[DLOG_CONS].current_index);
        log_current_line = false;
        // TODO mark discarded message
    }
}

// Commit a message that was issued as a series of parts (via do_log_part).
static void do_log_commit() noexcept
{
    if (log_current_line) {
        bool was_first = log_stream[DLOG_CONS].current_index == 0;
        log_stream[DLOG_CONS].current_index = log_stream[DLOG_CONS].log_buffer.get_length();
        if (was_first && log_to_console) {
            log_stream[DLOG_CONS].registerWith(&eventLoop, log_stream[DLOG_CONS].fd, out_events);
        }
    }
}

// Log a multi-part message beginning
void logMsgBegin(LogLevel lvl, const char *msg) noexcept
{
    // TODO use buffer
    log_current_line = lvl >= log_level;
    if (log_current_line) {
        if (log_to_console) {
            do_log_part("dinit: ");
            do_log_part(msg);
        }
    }
}

// Continue a multi-part log message
void logMsgPart(const char *msg) noexcept
{
    // TODO use buffer
    if (log_current_line) {
        if (log_to_console) {
            do_log_part(msg);
        }
    }
}

// Complete a multi-part log message
void logMsgEnd(const char *msg) noexcept
{
    // TODO use buffer
    if (log_current_line) {
        if (log_to_console) {
            do_log_part(msg);
            do_log_part("\n");
            do_log_commit();
        }
    }
}

void logServiceStarted(const char *service_name) noexcept
{
    do_log("[  OK  ] ", service_name, "\n");
}

void logServiceFailed(const char *service_name) noexcept
{
    do_log("[FAILED] ", service_name, "\n");
}

void logServiceStopped(const char *service_name) noexcept
{
    do_log("[STOPPD] ", service_name, "\n");
}
<|endoftext|>


<commit_before>// Copyright (C) M.Golov 2016
#include <iostream>
#include <string>
#include <functional>

struct InputData { int value; };
struct TransformedData { double value; };

InputData produceFx() { return InputData{42}; }
TransformedData transformFx(InputData input) { return TransformedData{(double)input.value}; }

template<typename TResult, typename TInput, typename TMeta>
std::function<TResult(TInput)> getFinalizer(TMeta) {
    throw std::runtime_error("getFinalizer must be specialized");
}

template<typename TContent>
struct Meta {
    using TMeta = std::string;
    TMeta meta;
    TContent content;

    template<typename TResult>
    Meta<TResult> transform(std::function<TResult(TContent)> fx) {
        return Meta<TResult>{meta, fx(content)};
    }

    template<typename TResult>
    TResult finalize() {
        const auto finalizer = getFinalizer<TResult, TContent, TMeta>(meta);
        return finalizer(content);
    }
};

Meta<InputData> producer() {
    return Meta<InputData>{"meta", produceFx()};
}

template<>
std::function<std::string(TransformedData)>
getFinalizer<std::string, TransformedData, Meta<TransformedData>::TMeta>(Meta<TransformedData>::TMeta meta) {
    return [meta](TransformedData content){
        return std::string("[") + meta + "]: " + std::to_string(content.value);
    };
}

int main(int argc, char **argv)
{
    Meta<InputData> input = producer();
    Meta<TransformedData> transformed = input.transform<TransformedData>(transformFx);
    std::string output = transformed.finalize<std::string>();
    std::cout << "Output: " << output << "\n";
    return 0;
}
<commit_msg>Added Backend<commit_after>// Copyright (C) M.Golov 2016
#include <iostream>
#include <string>
#include <functional>

struct InputData { int value; };
struct TransformedData { double value; };

InputData produceFx() { return InputData{42}; }
TransformedData transformFx(InputData input) { return TransformedData{(double)input.value}; }

template<typename TResult, typename TInput, typename TMeta>
std::function<TResult(TInput)> getFinalizer(TMeta) {
    throw std::runtime_error("getFinalizer must be specialized");
}

using MetaInfo = std::string;

template<typename TContent>
struct Meta {
    using TMeta = MetaInfo;
    TMeta meta;
    TContent content;

    template<typename TResult>
    Meta<TResult> transform(std::function<TResult(TContent)> fx) {
        return Meta<TResult>{meta, fx(content)};
    }

    template<typename TResult>
    TResult finalize() {
        const auto finalizer = getFinalizer<TResult, TContent, TMeta>(meta);
        return finalizer(content);
    }
};

Meta<InputData> producer() {
    return Meta<InputData>{"meta", produceFx()};
}

struct Backend {
    std::string finalize(MetaInfo info, TransformedData input) {
        return std::string("[") + info + "]: " + std::to_string(input.value);
    }
};

template<>
std::function<std::string(TransformedData)>
getFinalizer<std::string, TransformedData, Meta<TransformedData>::TMeta>(Meta<TransformedData>::TMeta meta) {
    return [meta](TransformedData content){
        return Backend().finalize(meta, content);
    };
}

int main(int argc, char **argv)
{
    Meta<InputData> input = producer();
    Meta<TransformedData> transformed = input.transform<TransformedData>(transformFx);
    std::string output = transformed.finalize<std::string>();
    std::cout << "Output: " << output << "\n";
    return 0;
}
<|endoftext|>


<commit_before>/** @file gsMultiPatch.hpp

    @brief Provides declaration of the MultiPatch class.

    This file is part of the G+Smo library.

    This Source Code Form is subject to the terms of the Mozilla Public
    License, v. 2.0. If a copy of the MPL was not distributed with this
    file, You can obtain one at http://mozilla.org/MPL/2.0/.

    Author(s): A. Mantzaflaris
*/

#pragma once

#include <iterator>

#include <gsCore/gsBasis.h>
#include <gsCore/gsGeometry.h>

#include <gsUtils/gsCombinatorics.h>

namespace gismo
{

template<class T>
gsMultiPatch<T>::gsMultiPatch(const gsGeometry<T> & geo )
    : gsBoxTopology( geo.parDim() )
{
    m_patches.push_back( geo.clone() );
    addBox();
    this->addAutoBoundaries();
}

template<class T>
gsMultiPatch<T>::gsMultiPatch( const gsMultiPatch& other )
    : gsBoxTopology( other ), m_patches( other.m_patches.size() )
{
    // clone all geometries
    cloneAll( other.m_patches.begin(), other.m_patches.end(),
              this->m_patches.begin() );
}

template<class T>
gsMultiPatch<T>::gsMultiPatch( const std::vector<gsGeometry<T> *>& patches )
    : gsBoxTopology( patches[0]->parDim(), patches.size() ) , m_patches( patches )
{
    this->addAutoBoundaries();
}

template<class T>
gsMultiPatch<T>::gsMultiPatch( const PatchContainer& patches,
                               const std::vector<patchSide>& boundary,
                               const std::vector<boundaryInterface>& interfaces )
    : gsBoxTopology( patches[0]->parDim(), patches.size(), boundary, interfaces ),
      m_patches( patches )
{ }

template<class T>
gsMultiPatch<T>::~gsMultiPatch()
{
    freeAll(m_patches);
}

template<class T>
int gsMultiPatch<T>::geoDim() const
{
    GISMO_ASSERT( m_patches.size() > 0 , "Empty multipatch object.");
    return m_patches[0]->geoDim();
}

template<class T>
int gsMultiPatch<T>::coDim() const
{
    GISMO_ASSERT( m_patches.size() > 0 , "Empty multipatch object.");
    return m_patches[0]->geoDim() - m_dim;
}

template<class T>
gsMatrix<T>
gsMultiPatch<T>::parameterRange(int i) const
{
    return m_patches[i]->basis().support();
}

template<class T>
gsBasis<T> &
gsMultiPatch<T>::basis( std::size_t i ) const
{
    GISMO_ASSERT( i < m_patches.size(), "Invalid patch index requested from gsMultiPatch" );
    return m_patches[i]->basis();
}

template<class T>
std::vector<gsBasis<T> *> gsMultiPatch<T>::basesCopy() const
{
    std::vector<gsBasis<T> *> bb;
    for ( typename PatchContainer::const_iterator it = m_patches.begin();
          it != m_patches.end(); ++it ) {
        bb.push_back( ( *it )->basis().clone() );
    }
    return bb ;
}

template<class T>
void gsMultiPatch<T>::addPatch( gsGeometry<T>* g )
{
    if ( m_dim == -1 ) {
        m_dim = g->parDim();
    } else {
        assert( m_dim == g->parDim() );
    }
    m_patches.push_back( g ) ;
    addBox();
}

template<class T>
int gsMultiPatch<T>::findPatchIndex( gsGeometry<T>* g ) const {
    typename PatchContainer::const_iterator it
            = std::find( m_patches.begin(), m_patches.end(), g );
    assert( it != m_patches.end() );
    return it - m_patches.begin();
}

template<class T>
void gsMultiPatch<T>::addInterface( gsGeometry<T>* g1, boxSide s1,
                                    gsGeometry<T>* g2, boxSide s2 ) {
    int p1 = findPatchIndex( g1 );
    int p2 = findPatchIndex( g2 );
    gsBoxTopology::addInterface( p1, s1, p2, s2 );
}

template<class T>
void gsMultiPatch<T>::uniformRefine(int numKnots, int mul)
{
    for ( typename PatchContainer::const_iterator it = m_patches.begin();
          it != m_patches.end(); ++it )
    {
        ( *it )->uniformRefine(numKnots, mul);
    }
}

/*
  This is based on comparing a set of reference points of the patch
  side and thus it implicitly assumes that that the patch faces match
*/
template<class T>
bool gsMultiPatch<T>::computeTopology( T tol )
{
    gsBoxTopology::clear();

    const size_t   np    = m_patches.size();
    const index_t  nCorP = 1 << m_dim;     // corners per patch
    const index_t  nCorS = 1 << (m_dim-1); // corners per side

    gsMatrix<T> supp,
    // Parametric coordinates of the reference points. These points
    // are used to decide if two sides match.
    // Currently these are the corner points and the side-centers
    coor(m_dim,nCorP + 2*m_dim*np);
    gsVector<bool> boxPar(m_dim);

    // each matrix contains the physical coordinates of the reference points
    std::vector<gsMatrix<T> > pCorners(np);

    std::vector<patchSide> pSide; // list of all candidate patchSides to compare
    pSide.reserve(np * 2 * m_dim);

    for (size_t p=0; p<np; ++p)
    {
        supp = m_patches[p]->parameterRange(); // the parameter domain of patch i

        // Corners' parametric coordinates
        for (boxCorner c=boxCorner::getFirst(m_dim); c<boxCorner::getEnd(m_dim); ++c)
        {
            boxPar   = c.parameters(m_dim);
            for (index_t i=0; i<m_dim;++i)
                coor(i,c-1) = boxPar(i) ? supp(i,1) : supp(i,0);
        }

        // Sides' centers parametric coordinates
        index_t l = nCorP;
        for (boxSide c=boxSide::getFirst(m_dim); c<boxSide::getEnd(m_dim); ++c)
        {
            const index_t dir = c.direction();
            const index_t par = c.parameter();

            for (index_t i=0; i<m_dim;++i)
                coor(i,l) = ( dir==i ? ( par?supp(i,1):supp(i,0) ) :
                                       (supp(i,1)+supp(i,0))/2.0 );
            l++;
        }

        // Evaluate the patch on the reference points
        m_patches[p]->eval_into(coor,pCorners[p]);

        // Add the patchSides for this patch to the candidate list
        for (boxSide bs=boxSide::getFirst(m_dim); bs<boxSide::getEnd(m_dim); ++bs)
            pSide.push_back(patchSide(p,bs));
    }

    gsVector<index_t>      dirMap(m_dim);
    gsVector<bool>         matched(nCorS), dirOr(m_dim);
    std::vector<boxCorner> cId1, cId2;
    cId1.reserve(nCorS);
    cId2.reserve(nCorS);

    while ( pSide.size() != 0 )
    {
        bool done=false;
        const patchSide side = pSide.back();
        pSide.pop_back();
        for (size_t other=0; other<pSide.size(); ++other)
        {
            side        .getContainedCorners(m_dim,cId1);
            pSide[other].getContainedCorners(m_dim,cId2);
            matched.setConstant(false);

            // Check whether the side center matches
            if ( ( pCorners[side.patch        ].col(nCorP+side-1        ) -
                   pCorners[pSide[other].patch].col(nCorP+pSide[other]-1)
                     ).norm() >= tol )
                continue;

            // Check whether the vertices match and compute direction map and orientation
            if ( matchVerticesOnSide( pCorners[side.patch], cId1, 0, pCorners[pSide[other].patch], cId2, matched, dirMap, dirOr, tol ) )
            {
                dirMap(side.direction()) = pSide[other].direction();
                dirOr(side.direction())   = !( side.parameter() == pSide[other].parameter() );
                gsBoxTopology::addInterface( boundaryInterface(side, pSide[other], dirMap, dirOr));
                // done with pSide[other], remove it from candidate list
                std::swap( pSide[other], pSide.back() );
                pSide.pop_back();
                done=true;
                break;//for (size_t other=0..)
            }
        }
        if (!done) // not an interface ?
            gsBoxTopology::addBoundary( side );
    }

    return true;
}

template <class T>
bool gsMultiPatch<T>::matchVerticesOnSide (
    const gsMatrix<T> &cc1, const std::vector<boxCorner> &ci1, index_t start,
    const gsMatrix<T> &cc2, const std::vector<boxCorner> &ci2, const gsVector<bool> &matched,
    gsVector<index_t> &dirMap, gsVector<bool>    &dirO,
    T tol,
    index_t reference)
{
    const bool computeOrientation = !(start&(start-1)) && (start != 0); // true if start is a power of 2
    const bool setReference       = start==0;          // if we search for the first point then we set the reference

    const int dim = cc1.rows();

    index_t o_dir = 0, d_dir = 0;

    gsVector<bool> refPar, newPar, newMatched;

    if (computeOrientation)
    {
        // o_dir is the only direction in which the parameters differ between start and 0
        const gsVector<bool> parStart = ci1[start].parameters(dim);
        const gsVector<bool> parRef   = ci1[0].parameters(dim);
        for (; o_dir<dim && parStart(o_dir)==parRef(o_dir)  ;) ++o_dir;
    }

    if (!setReference)
        refPar = ci2[reference].parameters(dim);

    for (size_t j=0;j<ci2.size();++j)
    {
        if( !matched(j) && (cc1.col(ci1[start]-1)-cc2.col(ci2[j]-1)).norm() < tol )
        {
            index_t newRef =   (setReference) ? j : reference;
            if (computeOrientation)
            {
                index_t count=0;
                d_dir = 0;
                newPar =  ci2[j].parameters(dim);
                for (index_t i=0; i< newPar.rows();++i)
                {
                    if ( newPar(i)!=refPar(i) )
                    {
                        d_dir=i;
                        ++count;
                    }
                }
                if (count != 1)
                {
                    // the match is wrong: we are mapping an edge to a diagonal
                    continue;
                }
                dirMap(o_dir) = d_dir;
                dirO  (o_dir) = (static_cast<index_t>(j) > reference);
            }
            if ( start + 1 == static_cast<index_t>( ci1.size() ) )
            {
                // we matched the last vertex, we are done
                return true;
            }
            newMatched = matched;
            newMatched(j) = true;
            if (matchVerticesOnSide( cc1,ci1,start+1,cc2,ci2,newMatched,dirMap,dirO, tol,newRef))
                return true;
        }
    }

    return false;
}

template<class T> // to do: move to boundaryInterface
gsAffineFunction<T> gsMultiPatch<T>::getMapForInterface(const boundaryInterface &bi, T scaling) const
{
    if (scaling==0)
        scaling=1;
    gsMatrix<T> box1=m_patches[bi.first().patch ]->support();
    gsMatrix<T> box2=m_patches[bi.second().patch]->support();
    const index_t oDir1 = bi.first() .direction();
    const index_t oDir2 = bi.second().direction();
    const T len1=box1(oDir1,1)-box1(oDir1,0);

    if (bi.second().parameter())
    {
        box2(oDir2,0)=box2(oDir2,1);
        box2(oDir2,1)+=scaling*len1;
    }
    else
    {
        box2(oDir2,1)=box2(oDir2,0);
        box2(oDir2,0)-=scaling*len1;
    }

    return gsAffineFunction<T>(bi.dirMap(bi.first()),bi.dirOrientation(bi.first()) ,box1,box2);
}

}
<commit_msg>small fix<commit_after>/** @file gsMultiPatch.hpp

    @brief Provides declaration of the MultiPatch class.

    This file is part of the G+Smo library.

    This Source Code Form is subject to the terms of the Mozilla Public
    License, v. 2.0. If a copy of the MPL was not distributed with this
    file, You can obtain one at http://mozilla.org/MPL/2.0/.

    Author(s): A. Mantzaflaris
*/

#pragma once

#include <iterator>

#include <gsCore/gsBasis.h>
#include <gsCore/gsGeometry.h>

#include <gsUtils/gsCombinatorics.h>

namespace gismo
{

template<class T>
gsMultiPatch<T>::gsMultiPatch(const gsGeometry<T> & geo )
    : gsBoxTopology( geo.parDim() )
{
    m_patches.push_back( geo.clone() );
    addBox();
    this->addAutoBoundaries();
}

template<class T>
gsMultiPatch<T>::gsMultiPatch( const gsMultiPatch& other )
    : gsBoxTopology( other ), m_patches( other.m_patches.size() )
{
    // clone all geometries
    cloneAll( other.m_patches.begin(), other.m_patches.end(),
              this->m_patches.begin() );
}

template<class T>
gsMultiPatch<T>::gsMultiPatch( const std::vector<gsGeometry<T> *>& patches )
    : gsBoxTopology( patches[0]->parDim(), patches.size() ) , m_patches( patches )
{
    this->addAutoBoundaries();
}

template<class T>
gsMultiPatch<T>::gsMultiPatch( const PatchContainer& patches,
                               const std::vector<patchSide>& boundary,
                               const std::vector<boundaryInterface>& interfaces )
    : gsBoxTopology( patches[0]->parDim(), patches.size(), boundary, interfaces ),
      m_patches( patches )
{ }

template<class T>
gsMultiPatch<T>::~gsMultiPatch()
{
    freeAll(m_patches);
}

template<class T>
int gsMultiPatch<T>::geoDim() const
{
    GISMO_ASSERT( m_patches.size() > 0 , "Empty multipatch object.");
    return m_patches[0]->geoDim();
}

template<class T>
int gsMultiPatch<T>::coDim() const
{
    GISMO_ASSERT( m_patches.size() > 0 , "Empty multipatch object.");
    return m_patches[0]->geoDim() - m_dim;
}

template<class T>
gsMatrix<T>
gsMultiPatch<T>::parameterRange(int i) const
{
    return m_patches[i]->basis().support();
}

template<class T>
gsBasis<T> &
gsMultiPatch<T>::basis( std::size_t i ) const
{
    GISMO_ASSERT( i < m_patches.size(), "Invalid patch index requested from gsMultiPatch" );
    return m_patches[i]->basis();
}

template<class T>
std::vector<gsBasis<T> *> gsMultiPatch<T>::basesCopy() const
{
    std::vector<gsBasis<T> *> bb;
    for ( typename PatchContainer::const_iterator it = m_patches.begin();
          it != m_patches.end(); ++it ) {
        bb.push_back( ( *it )->basis().clone() );
    }
    return bb ;
}

template<class T>
void gsMultiPatch<T>::addPatch( gsGeometry<T>* g )
{
    if ( m_dim == -1 ) {
        m_dim = g->parDim();
    } else {
        assert( m_dim == g->parDim() );
    }
    m_patches.push_back( g ) ;
    addBox();
}

template<class T>
int gsMultiPatch<T>::findPatchIndex( gsGeometry<T>* g ) const {
    typename PatchContainer::const_iterator it
            = std::find( m_patches.begin(), m_patches.end(), g );
    assert( it != m_patches.end() );
    return it - m_patches.begin();
}

template<class T>
void gsMultiPatch<T>::addInterface( gsGeometry<T>* g1, boxSide s1,
                                    gsGeometry<T>* g2, boxSide s2 ) {
    int p1 = findPatchIndex( g1 );
    int p2 = findPatchIndex( g2 );
    gsBoxTopology::addInterface( p1, s1, p2, s2 );
}

template<class T>
void gsMultiPatch<T>::uniformRefine(int numKnots, int mul)
{
    for ( typename PatchContainer::const_iterator it = m_patches.begin();
          it != m_patches.end(); ++it )
    {
        ( *it )->uniformRefine(numKnots, mul);
    }
}

/*
  This is based on comparing a set of reference points of the patch
  side and thus it implicitly assumes that that the patch faces match
*/
template<class T>
bool gsMultiPatch<T>::computeTopology( T tol )
{
    gsBoxTopology::clear();

    const size_t   np    = m_patches.size();
    const index_t  nCorP = 1 << m_dim;     // corners per patch
    const index_t  nCorS = 1 << (m_dim-1); // corners per side

    gsMatrix<T> supp,
    // Parametric coordinates of the reference points. These points
    // are used to decide if two sides match.
    // Currently these are the corner points and the side-centers
    coor(m_dim,nCorP + 2*m_dim);
    gsVector<bool> boxPar(m_dim);

    // each matrix contains the physical coordinates of the reference points
    std::vector<gsMatrix<T> > pCorners(np);

    std::vector<patchSide> pSide; // list of all candidate patchSides to compare
    pSide.reserve(np * 2 * m_dim);

    for (size_t p=0; p<np; ++p)
    {
        supp = m_patches[p]->parameterRange(); // the parameter domain of patch i

        // Corners' parametric coordinates
        for (boxCorner c=boxCorner::getFirst(m_dim); c<boxCorner::getEnd(m_dim); ++c)
        {
            boxPar   = c.parameters(m_dim);
            for (index_t i=0; i<m_dim;++i)
                coor(i,c-1) = boxPar(i) ? supp(i,1) : supp(i,0);
        }

        // Sides' centers parametric coordinates
        index_t l = nCorP;
        for (boxSide c=boxSide::getFirst(m_dim); c<boxSide::getEnd(m_dim); ++c)
        {
            const index_t dir = c.direction();
            const index_t par = c.parameter();

            for (index_t i=0; i<m_dim;++i)
                coor(i,l) = ( dir==i ? ( par?supp(i,1):supp(i,0) ) :
                                       (supp(i,1)+supp(i,0))/2.0 );
            l++;
        }

        // Evaluate the patch on the reference points
        m_patches[p]->eval_into(coor,pCorners[p]);

        // Add the patchSides for this patch to the candidate list
        for (boxSide bs=boxSide::getFirst(m_dim); bs<boxSide::getEnd(m_dim); ++bs)
            pSide.push_back(patchSide(p,bs));
    }

    gsVector<index_t>      dirMap(m_dim);
    gsVector<bool>         matched(nCorS), dirOr(m_dim);
    std::vector<boxCorner> cId1, cId2;
    cId1.reserve(nCorS);
    cId2.reserve(nCorS);

    while ( pSide.size() != 0 )
    {
        bool done=false;
        const patchSide side = pSide.back();
        pSide.pop_back();
        for (size_t other=0; other<pSide.size(); ++other)
        {
            side        .getContainedCorners(m_dim,cId1);
            pSide[other].getContainedCorners(m_dim,cId2);
            matched.setConstant(false);

            // Check whether the side center matches
            if ( ( pCorners[side.patch        ].col(nCorP+side-1        ) -
                   pCorners[pSide[other].patch].col(nCorP+pSide[other]-1)
                     ).norm() >= tol )
                continue;

            // Check whether the vertices match and compute direction map and orientation
            if ( matchVerticesOnSide( pCorners[side.patch], cId1, 0, pCorners[pSide[other].patch], cId2, matched, dirMap, dirOr, tol ) )
            {
                dirMap(side.direction()) = pSide[other].direction();
                dirOr (side.direction()) = !( side.parameter() == pSide[other].parameter() );
                gsBoxTopology::addInterface( boundaryInterface(side, pSide[other], dirMap, dirOr));
                // done with pSide[other], remove it from candidate list
                std::swap( pSide[other], pSide.back() );
                pSide.pop_back();
                done=true;
                break;//for (size_t other=0..)
            }
        }
        if (!done) // not an interface ?
            gsBoxTopology::addBoundary( side );
    }

    return true;
}

template <class T>
bool gsMultiPatch<T>::matchVerticesOnSide (
    const gsMatrix<T> &cc1, const std::vector<boxCorner> &ci1, index_t start,
    const gsMatrix<T> &cc2, const std::vector<boxCorner> &ci2, const gsVector<bool> &matched,
    gsVector<index_t> &dirMap, gsVector<bool>    &dirO,
    T tol,
    index_t reference)
{
    const bool computeOrientation = !(start&(start-1)) && (start != 0); // true if start is a power of 2
    const bool setReference       = start==0;          // if we search for the first point then we set the reference

    const int dim = cc1.rows();

    index_t o_dir = 0, d_dir = 0;

    gsVector<bool> refPar, newPar, newMatched;

    if (computeOrientation)
    {
        // o_dir is the only direction in which the parameters differ between start and 0
        const gsVector<bool> parStart = ci1[start].parameters(dim);
        const gsVector<bool> parRef   = ci1[0].parameters(dim);
        for (; o_dir<dim && parStart(o_dir)==parRef(o_dir)  ;) ++o_dir;
    }

    if (!setReference)
        refPar = ci2[reference].parameters(dim);

    for (size_t j=0;j<ci2.size();++j)
    {
        if( !matched(j) && (cc1.col(ci1[start]-1)-cc2.col(ci2[j]-1)).norm() < tol )
        {
            index_t newRef =   (setReference) ? j : reference;
            if (computeOrientation)
            {
                index_t count=0;
                d_dir = 0;
                newPar =  ci2[j].parameters(dim);
                for (index_t i=0; i< newPar.rows();++i)
                {
                    if ( newPar(i)!=refPar(i) )
                    {
                        d_dir=i;
                        ++count;
                    }
                }
                if (count != 1)
                {
                    // the match is wrong: we are mapping an edge to a diagonal
                    continue;
                }
                dirMap(o_dir) = d_dir;
                dirO  (o_dir) = (static_cast<index_t>(j) > reference);
            }
            if ( start + 1 == static_cast<index_t>( ci1.size() ) )
            {
                // we matched the last vertex, we are done
                return true;
            }
            newMatched = matched;
            newMatched(j) = true;
            if (matchVerticesOnSide( cc1,ci1,start+1,cc2,ci2,newMatched,dirMap,dirO, tol,newRef))
                return true;
        }
    }

    return false;
}

template<class T> // to do: move to boundaryInterface
gsAffineFunction<T> gsMultiPatch<T>::getMapForInterface(const boundaryInterface &bi, T scaling) const
{
    if (scaling==0)
        scaling=1;
    gsMatrix<T> box1=m_patches[bi.first().patch ]->support();
    gsMatrix<T> box2=m_patches[bi.second().patch]->support();
    const index_t oDir1 = bi.first() .direction();
    const index_t oDir2 = bi.second().direction();
    const T len1=box1(oDir1,1)-box1(oDir1,0);

    if (bi.second().parameter())
    {
        box2(oDir2,0)=box2(oDir2,1);
        box2(oDir2,1)+=scaling*len1;
    }
    else
    {
        box2(oDir2,1)=box2(oDir2,0);
        box2(oDir2,0)-=scaling*len1;
    }

    return gsAffineFunction<T>(bi.dirMap(bi.first()),bi.dirOrientation(bi.first()) ,box1,box2);
}

}
<|endoftext|>


<commit_before>#include "CameraAim.h"
#include "Subsystems/Chassis.h"
#include "Subsystems/Catapult.h"
#include "OI.h"
#include "Misc/Video.h"

CameraAim::CameraAim(Target_side side)
	: m_side(side)
	, m_prevAngle(0)
{
	Requires(Chassis::GetInstance());
}

// Called just before this Command runs the first time
void CameraAim::Initialize()
{
	timer.Reset();
	timer.Start();
	m_prevAngle = nan("NaN");
	RobotVideo::GetInstance()->SetHeadingQueueSize(0);
	RobotVideo::GetInstance()->SetLocationQueueSize(10);
}

// Called repeatedly when this Command is scheduled to run
void CameraAim::Execute()
{
	Chassis *chassis = Chassis::GetInstance();
	OI* oi = OI::GetInstance();
	if (chassis == nullptr or oi == nullptr) return;

	if (m_prevAngle == nan("NaN") or timer.Get() > AIM_COOLDOWN) {
		float turn = 0;
		float dist = 0;
		size_t nTurns = 0;

		RobotVideo::GetInstance()->mutex_lock();
		nTurns = RobotVideo::GetInstance()->HaveHeading();
		if(nTurns > 0) {
			turn = RobotVideo::GetInstance()->GetTurn(0);
			dist = RobotVideo::GetInstance()->GetDistance(0);
		}
		if(m_side == kRight and nTurns > 1) {
			turn = RobotVideo::GetInstance()->GetTurn(1);
			dist = RobotVideo::GetInstance()->GetDistance(1);
		}
		RobotVideo::GetInstance()->mutex_unlock();

		if (nTurns > 0) {
			if (dist > 0) {
				// Magic function.
				float catStop = 0.0917*(dist+90);
				if (catStop > Catapult::TOP_ZONE) catStop = Catapult::TOP_ZONE;
				if (catStop < Catapult::SLOW_ZONE) catStop = Catapult::SLOW_ZONE;
				Catapult::GetInstance()->toSetpoint(catStop);

				// The camera offset over the distance is the adjustment angle's tangent
				turn += atan2f(Preferences::GetInstance()->GetFloat("CameraOffset",RobotVideo::CAMERA_OFFSET), dist);
			}
			chassis->HoldAngle(turn);
			timer.Reset();
		}
	}
	else if (fabs(chassis->GetAngle() - m_prevAngle) > MAX_ANGULAR_V) {
		timer.Reset();
	}

	m_prevAngle = chassis->GetAngle();

	double moveSpeed = -oi->stickL->GetY();
	moveSpeed *= fabs(moveSpeed); // Square it here so the drivers will feel like it's squared
	chassis->DriveStraight(moveSpeed);
}

// Make this return true when this Command no longer needs to run execute()
bool CameraAim::IsFinished()
{
	return false;
}

// Called once after isFinished returns true
void CameraAim::End()
{

}

// Called when another command which requires one or more of the same
// subsystems is scheduled to run
void CameraAim::Interrupted()
{

}
<commit_msg>Separate the Magic Function<commit_after>#include "CameraAim.h"
#include "Subsystems/Chassis.h"
#include "Subsystems/Catapult.h"
#include "OI.h"
#include "Misc/Video.h"

CameraAim::CameraAim(Target_side side)
	: m_side(side)
	, m_prevAngle(0)
{
	Requires(Chassis::GetInstance());
}

// Called just before this Command runs the first time
void CameraAim::Initialize()
{
	timer.Reset();
	timer.Start();
	m_prevAngle = nan("NaN");
	RobotVideo::GetInstance()->SetHeadingQueueSize(0);
	RobotVideo::GetInstance()->SetLocationQueueSize(10);
}

/**
 * \brief Magic function that returns desired stop angle in rope inches
 *
 * The data collected from repeated shooting at the last night of the build
 * season suggest that the stop angle of the catapult is pretty much a linear
 * function. Here we are going to account for the robot's velocity related
 * to the tower.
 */
double calculateStop(double dist, double speed=0)
{
	return 0.0917 * (dist + 90);
}

// Called repeatedly when this Command is scheduled to run
void CameraAim::Execute()
{
	Chassis *chassis = Chassis::GetInstance();
	OI* oi = OI::GetInstance();
	if (chassis == nullptr or oi == nullptr) return;

	if (m_prevAngle == nan("NaN") or timer.Get() > AIM_COOLDOWN) {
		float turn = 0;
		float dist = 0;
		size_t nTurns = 0;

		RobotVideo::GetInstance()->mutex_lock();
		nTurns = RobotVideo::GetInstance()->HaveHeading();
		if(nTurns > 0) {
			turn = RobotVideo::GetInstance()->GetTurn(0);
			dist = RobotVideo::GetInstance()->GetDistance(0);
		}
		if(m_side == kRight and nTurns > 1) {
			turn = RobotVideo::GetInstance()->GetTurn(1);
			dist = RobotVideo::GetInstance()->GetDistance(1);
		}
		RobotVideo::GetInstance()->mutex_unlock();

		if (nTurns > 0) {
			if (dist > 0) {
				// Call the Magic function to determine the stop angle.
				float catStop = calculateStop(dist);
				if (catStop > Catapult::TOP_ZONE) catStop = Catapult::TOP_ZONE;
				if (catStop < Catapult::SLOW_ZONE) catStop = Catapult::SLOW_ZONE;
				Catapult::GetInstance()->toSetpoint(catStop);

				// The camera offset over the distance is the adjustment angle's tangent
				turn += atan2f(Preferences::GetInstance()->GetFloat("CameraOffset",RobotVideo::CAMERA_OFFSET), dist);
			}
			chassis->HoldAngle(turn);
			timer.Reset();
		}
	}
	else if (fabs(chassis->GetAngle() - m_prevAngle) > MAX_ANGULAR_V) {
		timer.Reset();
	}

	m_prevAngle = chassis->GetAngle();

	double moveSpeed = -oi->stickL->GetY();
	moveSpeed *= fabs(moveSpeed); // Square it here so the drivers will feel like it's squared
	chassis->DriveStraight(moveSpeed);
}

// Make this return true when this Command no longer needs to run execute()
bool CameraAim::IsFinished()
{
	return false;
}

// Called once after isFinished returns true
void CameraAim::End()
{

}

// Called when another command which requires one or more of the same
// subsystems is scheduled to run
void CameraAim::Interrupted()
{

}
<|endoftext|>


<commit_before>#include "Halide.h"
#include "wrapper_ger.h"
#include <tiramisu/utils.h>
#include <cstdlib>
#include <iostream>
#include <chrono>
using namespace std;
using namespace std::chrono;
#define MM 100
#define NN 200
#define alpha 3
int main(int, char **)
{
    Halide::Buffer<uint8_t> A_buf(NN, MM);
    Halide::Buffer<uint8_t> X_buf(MM);
    Halide::Buffer<uint8_t> Y_buf(NN);
    // Initialize matrix A with pseudorandom values:
    for (int i = 0; i < MM; i++) {
        for (int j = 0; j < NN; j++) {
            A_buf(j, i) = (i + 3) * (j + 1);
        }

    }
    // Initialize Vector X with pseudorandom values:
    for(int i=0 ; i<MM ;i++){
        X_buf(i) = (i + 1) ;

    }
    // Initialize Vector Y with pseudorandom values:
    for(int i=0 ; i<NN ;i++){
        Y_buf(i) = i ;

    }
    // Output buffer
    Halide::Buffer<uint8_t> C_buf(NN, MM);
    init_buffer(C_buf, (uint8_t)0);
    // TRAMISU CODE EXECUTION STARTS:
    auto start1 = std::chrono::high_resolution_clock::now();
    ger(A_buf.raw_buffer(), X_buf.raw_buffer(),Y_buf.raw_buffer(),C_buf.raw_buffer());
    auto end1 = std::chrono::high_resolution_clock::now();
    auto  duration1 =duration_cast<microseconds>(end1 - start1);
    // TRAMISU CODE EXECUTION ENDS.
    // REFERENCE Output buffer
    Halide::Buffer<uint8_t> C2_buf(NN, MM);
    init_buffer(C2_buf, (uint8_t)0);
    // REFERENCE C++ CODE EXECUTION STARTS:
    auto start2 = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < MM; i++) {
        for (int j = 0; j < NN; j++) {
                C2_buf(j, i) = A_buf(j, i) +(X_buf(i)*Y_buf(j))*alpha;
         }
    }
    auto end2 = std::chrono::high_resolution_clock::now();
    auto  duration2 =duration_cast<microseconds>(end2 - start2);
    // REFERENCE C++ CODE EXECUTION ENDS.
   // printing REFERECE EXEC TIME:
    std::cout << "\n REF RESOLUTION TIME : " << duration2.count() << "microseconds";
   // printing TIRAMISU EXEC TIME:
    std::cout << "\n TIRAMISU RESOLUTION TIME : " << duration1.count() << "microseconds";
    printf("\n");
   // Verify if TIRAMISU output is correct:
    compare_buffers("ger", C_buf, C2_buf);
    printf("\n");
    return 0;
}
<commit_msg>Update wrapper_ger.cpp<commit_after>#include "Halide.h"
#include "wrapper_ger.h"
#include <tiramisu/utils.h>
#include <cstdlib>
#include <iostream>
#include <chrono>

using namespace std;
using namespace std::chrono;

#define MM 100
#define NN 200
#define alpha 3

int main(int, char **)
{
    Halide::Buffer<uint8_t> A_buf(NN, MM);
    Halide::Buffer<uint8_t> X_buf(MM);
    Halide::Buffer<uint8_t> Y_buf(NN);

    // Initialize matrix A with pseudorandom values:
    for (int i = 0; i < MM; i++)
    {
        for (int j = 0; j < NN; j++)
        {
            A_buf(j, i) = (i + 3) * (j + 1);
        }

    }

    // Initialize Vector X with pseudorandom values:
    for(int i=0 ; i<MM ;i++)
    {
        X_buf(i) = (i + 1) ;
    }

    // Initialize Vector Y with pseudorandom values:
    for(int i=0 ; i<NN ;i++)
    {
        Y_buf(i) = i ;
    }

    // Output buffer
    Halide::Buffer<uint8_t> C_buf(NN, MM);
    init_buffer(C_buf, (uint8_t)0);

    // TRAMISU CODE EXECUTION STARTS:
    auto start1 = std::chrono::high_resolution_clock::now();
    ger(A_buf.raw_buffer(), X_buf.raw_buffer(),Y_buf.raw_buffer(),C_buf.raw_buffer());
    auto end1 = std::chrono::high_resolution_clock::now();
    auto  duration1 =duration_cast<microseconds>(end1 - start1);

    // TRAMISU CODE EXECUTION ENDS.
    // REFERENCE Output buffer
    Halide::Buffer<uint8_t> C2_buf(NN, MM);
    init_buffer(C2_buf, (uint8_t)0);

    // REFERENCE C++ CODE EXECUTION STARTS:
    auto start2 = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < MM; i++)
    {
        for (int j = 0; j < NN; j++)
        {
                C2_buf(j, i) = A_buf(j, i) +(X_buf(i)*Y_buf(j))*alpha;
         }
    }

    auto end2 = std::chrono::high_resolution_clock::now();
    auto  duration2 =duration_cast<microseconds>(end2 - start2);

    // REFERENCE C++ CODE EXECUTION ENDS.
    // printing REFERECE EXEC TIME:
    std::cout << "\n REF RESOLUTION TIME : " << duration2.count() << "microseconds";

    // printing TIRAMISU EXEC TIME:
    std::cout << "\n TIRAMISU RESOLUTION TIME : " << duration1.count() << "microseconds";
    printf("\n");

    // Verify if TIRAMISU output is correct:
    compare_buffers("ger", C_buf, C2_buf);
    printf("\n");

    return 0;
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2013.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <iostream>
#include <fstream>
#include <sstream>

#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>

#include "earnings.hpp"
#include "args.hpp"
#include "accounts.hpp"
#include "data.hpp"
#include "guid.hpp"
#include "config.hpp"
#include "utils.hpp"
#include "console.hpp"
#include "budget_exception.hpp"

using namespace budget;

namespace {

static data_handler<earning> earnings;

void show_earnings(boost::gregorian::greg_month month, boost::gregorian::greg_year year){
    std::vector<std::string> columns = {"ID", "Date", "Account", "Name", "Amount"};
    std::vector<std::vector<std::string>> contents;

    money total;
    std::size_t count = 0;

    for(auto& earning : earnings.data){
        if(earning.date.year() == year && earning.date.month() == month){
            contents.push_back({to_string(earning.id), to_string(earning.date), get_account(earning.account).name, earning.name, to_string(earning.amount)});

            total += earning.amount;
            ++count;
        }
    }

    if(count == 0){
        std::cout << "No earnings for " << month << "-" << year << std::endl;
    } else {
        contents.push_back({"", "", "", "Total", to_string(total)});

        display_table(columns, contents);
    }
}

void show_earnings(boost::gregorian::greg_month month){
    auto today = boost::gregorian::day_clock::local_day();

    show_earnings(month, today.year());
}

void show_earnings(){
    auto today = boost::gregorian::day_clock::local_day();

    show_earnings(today.month(), today.year());
}

void show_all_earnings(){
    std::vector<std::string> columns = {"ID", "Date", "Account", "Name", "Amount"};
    std::vector<std::vector<std::string>> contents;

    for(auto& earning : earnings.data){
        contents.push_back({to_string(earning.id), to_string(earning.date), get_account(earning.account).name, earning.name, to_string(earning.amount)});
    }

    display_table(columns, contents);
}

void validate_name(const std::string& name){
    if(name.empty()){
        throw budget_exception("The name of the earning cannot be empty");
    }
}

} //end of anonymous namespace

void budget::earnings_module::load(){
    load_earnings();
    load_accounts();
}

void budget::earnings_module::unload(){
    save_earnings();
}

void budget::earnings_module::handle(const std::vector<std::string>& args){
    if(args.size() == 1){
        show_earnings();
    } else {
        auto& subcommand = args[1];

        if(subcommand == "show"){
            if(args.size() == 2){
                show_earnings();
            } else if(args.size() == 3){
                show_earnings(boost::gregorian::greg_month(to_number<unsigned short>(args[2])));
            } else if(args.size() == 4){
                show_earnings(
                    boost::gregorian::greg_month(to_number<unsigned short>(args[2])),
                    boost::gregorian::greg_year(to_number<unsigned short>(args[3])));
            } else {
                throw budget_exception("Too many arguments to earning show");
            }
        } else if(subcommand == "all"){
            show_all_earnings();
        } else if(subcommand == "add"){
            enough_args(args, 5);

            earning earning;
            earning.guid = generate_guid();
            earning.date = boost::gregorian::day_clock::local_day();

            auto account_name = args[2];
            validate_account(account_name);
            earning.account = get_account(account_name).id;

            earning.amount = parse_money(args[3]);
            not_negative(earning.amount);

            for(std::size_t i = 4; i < args.size(); ++i){
                earning.name += args[i] + " ";
            }

            validate_name(earning.name);

            add_data(earnings, std::move(earning));
        } else if(subcommand == "addd"){
            enough_args(args, 6);

            earning earning;
            earning.guid = generate_guid();
            earning.date = boost::gregorian::from_string(args[2]);

            auto account_name = args[3];
            validate_account(account_name);
            earning.account = get_account(account_name).id;

            earning.amount = parse_money(args[4]);
            not_negative(earning.amount);

            for(std::size_t i = 5; i < args.size(); ++i){
                earning.name += args[i] + " ";
            }

            validate_name(earning.name);

            add_data(earnings, std::move(earning));
        } else if(subcommand == "delete"){
            enough_args(args, 3);

            std::size_t id = to_number<std::size_t>(args[2]);

            if(!exists(earnings, id)){
                throw budget_exception("There are no earning with id ");
            }

            remove(earnings, id);

            std::cout << "earning " << id << " has been deleted" << std::endl;
        } else if(subcommand == "edit"){
            enough_args(args, 3);

            std::size_t id = to_number<std::size_t>(args[2]);

            if(!exists(earnings, id)){
                throw budget_exception("There are no earning with id " + args[2]);
            }

            auto& earning = get(earnings, id);

            edit_date(earning.date, "Date");

            auto account_name = get_account(earning.account).name;
            edit_string(account_name, "Account");
            validate_account(account_name);
            earning.account = get_account(account_name).id;

            edit_string(earning.name, "Name");
            validate_name(earning.name);

            edit_money(earning.amount, "Amount");
            not_negative(earning.amount);

            std::cout << "earning " << id << " has been modified" << std::endl;
        } else {
            throw budget_exception("Invalid subcommand \"" + subcommand + "\"");
        }
    }
}

void budget::load_earnings(){
    load_data(earnings, "earnings.data");
}

void budget::save_earnings(){
    save_data(earnings, "earnings.data");
}

std::ostream& budget::operator<<(std::ostream& stream, const earning& earning){
    return stream << earning.id  << ':' << earning.guid << ':' << earning.account << ':' << earning.name << ':' << earning.amount << ':' << to_string(earning.date);
}

void budget::operator>>(const std::vector<std::string>& parts, earning& earning){
    earning.id = to_number<std::size_t>(parts[0]);
    earning.guid = parts[1];
    earning.account = to_number<std::size_t>(parts[2]);
    earning.name = parts[3];
    earning.amount = parse_money(parts[4]);
    earning.date = boost::gregorian::from_string(parts[5]);
}

std::vector<earning>& budget::all_earnings(){
    return earnings.data;
}
<commit_msg>Implement the new creation system for earning<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2013.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <iostream>
#include <fstream>
#include <sstream>

#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>

#include "earnings.hpp"
#include "args.hpp"
#include "accounts.hpp"
#include "data.hpp"
#include "guid.hpp"
#include "config.hpp"
#include "utils.hpp"
#include "console.hpp"
#include "budget_exception.hpp"

using namespace budget;

namespace {

static data_handler<earning> earnings;

void show_earnings(boost::gregorian::greg_month month, boost::gregorian::greg_year year){
    std::vector<std::string> columns = {"ID", "Date", "Account", "Name", "Amount"};
    std::vector<std::vector<std::string>> contents;

    money total;
    std::size_t count = 0;

    for(auto& earning : earnings.data){
        if(earning.date.year() == year && earning.date.month() == month){
            contents.push_back({to_string(earning.id), to_string(earning.date), get_account(earning.account).name, earning.name, to_string(earning.amount)});

            total += earning.amount;
            ++count;
        }
    }

    if(count == 0){
        std::cout << "No earnings for " << month << "-" << year << std::endl;
    } else {
        contents.push_back({"", "", "", "Total", to_string(total)});

        display_table(columns, contents);
    }
}

void show_earnings(boost::gregorian::greg_month month){
    auto today = boost::gregorian::day_clock::local_day();

    show_earnings(month, today.year());
}

void show_earnings(){
    auto today = boost::gregorian::day_clock::local_day();

    show_earnings(today.month(), today.year());
}

void show_all_earnings(){
    std::vector<std::string> columns = {"ID", "Date", "Account", "Name", "Amount"};
    std::vector<std::vector<std::string>> contents;

    for(auto& earning : earnings.data){
        contents.push_back({to_string(earning.id), to_string(earning.date), get_account(earning.account).name, earning.name, to_string(earning.amount)});
    }

    display_table(columns, contents);
}

void validate_name(const std::string& name){
    if(name.empty()){
        throw budget_exception("The name of the earning cannot be empty");
    }
}

} //end of anonymous namespace

void budget::earnings_module::load(){
    load_earnings();
    load_accounts();
}

void budget::earnings_module::unload(){
    save_earnings();
}

void budget::earnings_module::handle(const std::vector<std::string>& args){
    if(args.size() == 1){
        show_earnings();
    } else {
        auto& subcommand = args[1];

        if(subcommand == "show"){
            if(args.size() == 2){
                show_earnings();
            } else if(args.size() == 3){
                show_earnings(boost::gregorian::greg_month(to_number<unsigned short>(args[2])));
            } else if(args.size() == 4){
                show_earnings(
                    boost::gregorian::greg_month(to_number<unsigned short>(args[2])),
                    boost::gregorian::greg_year(to_number<unsigned short>(args[3])));
            } else {
                throw budget_exception("Too many arguments to earning show");
            }
        } else if(subcommand == "all"){
            show_all_earnings();
        } else if(subcommand == "add"){
            if(args.size() == 2){
                earning earning;
                earning.guid = generate_guid();
                earning.date = boost::gregorian::day_clock::local_day();

                edit_date(earning.date, "Date");

                std::string account_name;
                edit_string(account_name, "Account");
                validate_account(account_name);
                earning.account = get_account(account_name).id;

                edit_string(earning.name, "Name");
                validate_name(earning.name);

                edit_money(earning.amount, "Amount");
                not_negative(earning.amount);

                add_data(earnings, std::move(earning));
            } else {
                enough_args(args, 5);

                earning earning;
                earning.guid = generate_guid();
                earning.date = boost::gregorian::day_clock::local_day();

                auto account_name = args[2];
                validate_account(account_name);
                earning.account = get_account(account_name).id;

                earning.amount = parse_money(args[3]);
                not_negative(earning.amount);

                for(std::size_t i = 4; i < args.size(); ++i){
                    earning.name += args[i] + " ";
                }

                validate_name(earning.name);

                add_data(earnings, std::move(earning));
            }
        } else if(subcommand == "addd"){
            enough_args(args, 6);

            earning earning;
            earning.guid = generate_guid();
            earning.date = boost::gregorian::from_string(args[2]);

            auto account_name = args[3];
            validate_account(account_name);
            earning.account = get_account(account_name).id;

            earning.amount = parse_money(args[4]);
            not_negative(earning.amount);

            for(std::size_t i = 5; i < args.size(); ++i){
                earning.name += args[i] + " ";
            }

            validate_name(earning.name);

            add_data(earnings, std::move(earning));
        } else if(subcommand == "delete"){
            enough_args(args, 3);

            std::size_t id = to_number<std::size_t>(args[2]);

            if(!exists(earnings, id)){
                throw budget_exception("There are no earning with id ");
            }

            remove(earnings, id);

            std::cout << "earning " << id << " has been deleted" << std::endl;
        } else if(subcommand == "edit"){
            enough_args(args, 3);

            std::size_t id = to_number<std::size_t>(args[2]);

            if(!exists(earnings, id)){
                throw budget_exception("There are no earning with id " + args[2]);
            }

            auto& earning = get(earnings, id);

            edit_date(earning.date, "Date");

            auto account_name = get_account(earning.account).name;
            edit_string(account_name, "Account");
            validate_account(account_name);
            earning.account = get_account(account_name).id;

            edit_string(earning.name, "Name");
            validate_name(earning.name);

            edit_money(earning.amount, "Amount");
            not_negative(earning.amount);

            std::cout << "earning " << id << " has been modified" << std::endl;
        } else {
            throw budget_exception("Invalid subcommand \"" + subcommand + "\"");
        }
    }
}

void budget::load_earnings(){
    load_data(earnings, "earnings.data");
}

void budget::save_earnings(){
    save_data(earnings, "earnings.data");
}

std::ostream& budget::operator<<(std::ostream& stream, const earning& earning){
    return stream << earning.id  << ':' << earning.guid << ':' << earning.account << ':' << earning.name << ':' << earning.amount << ':' << to_string(earning.date);
}

void budget::operator>>(const std::vector<std::string>& parts, earning& earning){
    earning.id = to_number<std::size_t>(parts[0]);
    earning.guid = parts[1];
    earning.account = to_number<std::size_t>(parts[2]);
    earning.name = parts[3];
    earning.amount = parse_money(parts[4]);
    earning.date = boost::gregorian::from_string(parts[5]);
}

std::vector<earning>& budget::all_earnings(){
    return earnings.data;
}
<|endoftext|>


<commit_before>#include "recv_buf.h"
#include "process_http.h"
#include <map>
#include <string>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <cstring>
#include <cstdio> /* std::perror */
#include <cstdlib>
#include <unistd.h>

#define PORT "12345"

#define RESPHEADERGOOD \
"HTTP/1.1 200 OK\r\n" \
"Content-Type: text/html\r\n\r\n"
#define RESPHEADERBAD \
"HTTP/1.1 404 Not Found\r\n" \
"Content-Type: text/html\r\n\r\n" \
"Page does not exist.\r\n"
#define RESPBODYGET \
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n" \
"\n" \
"\n" \
"<meta http-equiv=\"Content-type\" content=\"text/html;charset=UTF-8\">\n" \
"<title>Upload</title>\n" \
"\n" \
"<form enctype=\"multipart/form-data\" action=\".\" method=\"POST\">\n" \
"
Choose a file to upload: <input id=\"up\" name=\"up\" type=\"file\">\n" \
"
<input type=\"submit\" value=\"Upload it\">\n" \
"</form>\n"
#define RESPBODYPOST \
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n" \
"\n" \
"\n" \
"<meta http-equiv=\"Content-type\" content=\"text/html;charset=UTF-8\">\n" \
"<title>Done</title>\n" \
"\n" \
"
Done. You've uploaded it.\n"

#define DEFAULT_MAGIC "/"

using namespace std;

int setup_sockets(struct addrinfo *theirs, socklen_t *addr_size);

int main(int argc, char *argv[]) {

	string magic;
	if (argc <= 1) {
		magic = DEFAULT_MAGIC;
	} else {
		magic = argv[1];
	}
	if (magic[0] != '/') {
		magic = "/" + magic;
	}

	int accepted;
	struct addrinfo theirs;
	socklen_t addr_size;

	/* READ DATA */
	accepted = setup_sockets(&theirs, &addr_size);

	http_info headers = parse_headers(accepted);
	if (headers.http_version == "HTTP/1.1" && !headers.headers.count("Host")) {
		cerr << "Error: No \"Host\" header using HTTP v1.1. The user's sending bad data.\n"
			"http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.6.1.1\n";
	} else if (headers.headers.count("Host")) {
#ifdef TEE
		cout << "The user wanted the host " << headers.headers["Host"] << "\n\n";
#endif
	}

	if (percent_decode(headers.request_uri) == magic) {
		send(accepted, RESPHEADERGOOD, sizeof(RESPHEADERGOOD), 0);
		if (headers.method == "GET") {
			send(accepted, RESPBODYGET, sizeof(RESPBODYGET), 0);
		} else if (headers.method == "POST") {
			string body = get_body(accepted, headers);
#ifdef TEE
			cout << "Body (true length " << body.size() << "):\n" << body;
#endif
			send(accepted, RESPBODYPOST, sizeof(RESPBODYPOST), 0);
		}
	} else {
		send(accepted, RESPHEADERBAD, sizeof(RESPHEADERBAD), 0);
	}

	close(accepted);

	exit(EXIT_SUCCESS);
}

int setup_sockets(struct addrinfo *theirs, socklen_t *addr_size) {
	int status;
	struct addrinfo hints,
			*res,
			*p;
	int sockfd,
	    ret;
	int yes=1;

	memset(&hints, 0, sizeof(hints));
	hints.ai_family = AF_UNSPEC; /* IPv4 or IPv6 */
	hints.ai_socktype = SOCK_STREAM; /* TCP */
	hints.ai_flags = AI_PASSIVE;

	/* getaddrinfo() to ser up the socket data */
	if ((status = getaddrinfo(NULL, PORT, &hints, &res)) != 0) {
		cerr << "getaddrinfo: " << gai_strerror(status) << '\n';
		exit(EXIT_FAILURE);
	}

	for (p = res; p != NULL; p = p->ai_next) {

		/* Get the server socket */
		if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
			perror("socket");
			continue;
		}
		if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
			perror("setsockopt");
			exit(EXIT_FAILURE);
		}

		/* Bind to the port */
		if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
			close(sockfd);
			perror("bind");
			continue;
		}

		break;
	}
	if (p == NULL) {
		cerr << "Failed to bind.\n";
		exit(EXIT_FAILURE);
	}

	freeaddrinfo(res);

	/* Listen for incoming connections */
	if (listen(sockfd, 5) == -1) {
		perror("listen");
		exit(EXIT_FAILURE);
	}

	/* Accept a connection */
	*addr_size = sizeof(*theirs);
	if ((ret = accept(sockfd, (struct sockaddr *)theirs, addr_size)) == -1) {
		perror("accept");
		exit(EXIT_FAILURE);
	}

	/* Free up the server data */
	close(sockfd);

	return ret;
}
<commit_msg>Process 100-continue headers<commit_after>#include "recv_buf.h"
#include "process_http.h"
#include <map>
#include <string>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <cstring>
#include <cstdio> /* std::perror */
#include <cstdlib>
#include <unistd.h>

#define PORT "12345"

#define RESPHEADERGOOD \
"HTTP/1.1 200 OK\r\n" \
"Content-Type: text/html\r\n\r\n"
#define RESPHEADERBAD \
"HTTP/1.1 404 Not Found\r\n" \
"Content-Type: text/html\r\n\r\n" \
"Page does not exist.\r\n"
#define RESPHEADERCONTINUE \
"HTTP/1.1 100 Continue\r\n\r\n"
#define RESPBODYGET \
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n" \
"\n" \
"\n" \
"<meta http-equiv=\"Content-type\" content=\"text/html;charset=UTF-8\">\n" \
"<title>Upload</title>\n" \
"\n" \
"<form enctype=\"multipart/form-data\" action=\".\" method=\"POST\">\n" \
"
Choose a file to upload: <input id=\"up\" name=\"up\" type=\"file\">\n" \
"
<input type=\"submit\" value=\"Upload it\">\n" \
"</form>\n"
#define RESPBODYPOST \
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n" \
"\n" \
"\n" \
"<meta http-equiv=\"Content-type\" content=\"text/html;charset=UTF-8\">\n" \
"<title>Done</title>\n" \
"\n" \
"
Done. You've uploaded it.\n"

#define DEFAULT_MAGIC "/"

using namespace std;

int setup_sockets(struct addrinfo *theirs, socklen_t *addr_size);

int main(int argc, char *argv[]) {

	string magic;
	if (argc <= 1) {
		magic = DEFAULT_MAGIC;
	} else {
		magic = argv[1];
	}
	if (magic[0] != '/') {
		magic = "/" + magic;
	}

	int accepted;
	struct addrinfo theirs;
	socklen_t addr_size;

	/* READ DATA */
	accepted = setup_sockets(&theirs, &addr_size);

	http_info headers = parse_headers(accepted);
	if (headers.http_version == "HTTP/1.1" && !headers.headers.count("Host")) {
		cerr << "Error: No \"Host\" header using HTTP v1.1. The user's sending bad data.\n"
			"http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.6.1.1\n";
	} else if (headers.headers.count("Host")) {
#ifdef TEE
		cout << "The user wanted the host " << headers.headers["Host"] << "\n\n";
#endif
	}

	if (percent_decode(headers.request_uri) == magic) {
		if (headers.method == "GET") {
			send(accepted, RESPHEADERGOOD, sizeof(RESPHEADERGOOD), 0);
			send(accepted, RESPBODYGET, sizeof(RESPBODYGET), 0);
		} else if (headers.method == "POST") {
			if (headers.headers.count("Expect") && headers.headers["Expect"] == "100-continue") {
				send(accepted, RESPHEADERCONTINUE, sizeof(RESPHEADERCONTINUE), 0);
			}
			string body = get_body(accepted, headers);
			send(accepted, RESPHEADERGOOD, sizeof(RESPHEADERGOOD), 0);
#ifdef TEE
			cout << "Body (true length " << body.size() << "):\n" << body;
#endif
			send(accepted, RESPBODYPOST, sizeof(RESPBODYPOST), 0);
		}
	} else {
		send(accepted, RESPHEADERBAD, sizeof(RESPHEADERBAD), 0);
	}

	close(accepted);

	exit(EXIT_SUCCESS);
}

int setup_sockets(struct addrinfo *theirs, socklen_t *addr_size) {
	int status;
	struct addrinfo hints,
			*res,
			*p;
	int sockfd,
	    ret;
	int yes=1;

	memset(&hints, 0, sizeof(hints));
	hints.ai_family = AF_UNSPEC; /* IPv4 or IPv6 */
	hints.ai_socktype = SOCK_STREAM; /* TCP */
	hints.ai_flags = AI_PASSIVE;

	/* getaddrinfo() to ser up the socket data */
	if ((status = getaddrinfo(NULL, PORT, &hints, &res)) != 0) {
		cerr << "getaddrinfo: " << gai_strerror(status) << '\n';
		exit(EXIT_FAILURE);
	}

	for (p = res; p != NULL; p = p->ai_next) {

		/* Get the server socket */
		if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
			perror("socket");
			continue;
		}
		if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
			perror("setsockopt");
			exit(EXIT_FAILURE);
		}

		/* Bind to the port */
		if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
			close(sockfd);
			perror("bind");
			continue;
		}

		break;
	}
	if (p == NULL) {
		cerr << "Failed to bind.\n";
		exit(EXIT_FAILURE);
	}

	freeaddrinfo(res);

	/* Listen for incoming connections */
	if (listen(sockfd, 5) == -1) {
		perror("listen");
		exit(EXIT_FAILURE);
	}

	/* Accept a connection */
	*addr_size = sizeof(*theirs);
	if ((ret = accept(sockfd, (struct sockaddr *)theirs, addr_size)) == -1) {
		perror("accept");
		exit(EXIT_FAILURE);
	}

	/* Free up the server data */
	close(sockfd);

	return ret;
}
<|endoftext|>


<commit_before>#include <QtGui/QApplication>
#include "qmlapplicationviewer.h"

#include <QDebug>

#include <QtDeclarative>
#include <QDebug>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
	app.setApplicationName("wanderer");
	app.setApplicationVersion("0.1");
	app.setOrganizationName("sauron");
	app.setOrganizationDomain("http://co-de.org");

	QmlApplicationViewer viewer;

	//HACK
	QDir dir("../qmlbinding");
	foreach (QString plugin, dir.entryList()) {
		QString error;
		viewer.engine()->importPlugin(dir.absoluteFilePath(plugin), QLatin1String("UbuntuOne"), &error);
	}

	viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
	viewer.setMainQmlFile(QLatin1String("qml/client/main.qml"));
	viewer.setMinimumSize(300, 400);
	viewer.showExpanded();
	return app.exec();
}
<commit_msg>Hardcoded oxygen theme<commit_after>#include <QtGui/QApplication>
#include "qmlapplicationviewer.h"

#include <QDebug>

#include <QtDeclarative>
#include <QDebug>
#include <QIcon>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
	app.setApplicationName("wanderer");
	app.setApplicationVersion("0.1");
	app.setOrganizationName("sauron");
	app.setOrganizationDomain("http://co-de.org");

	QmlApplicationViewer viewer;

	//HACK
	QDir dir("../qmlbinding");
	foreach (QString plugin, dir.entryList()) {
		QString error;
		viewer.engine()->importPlugin(dir.absoluteFilePath(plugin), QLatin1String("UbuntuOne"), &error);
	}
	if (QIcon::themeName().isEmpty())
		QIcon::setThemeName("oxygen");

	viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
	viewer.setMainQmlFile(QLatin1String("qml/client/main.qml"));
	viewer.setMinimumSize(300, 400);
	viewer.showExpanded();
	return app.exec();
}
<|endoftext|>


<commit_before>// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#include "performance_runner.h"
#include "TestCase.h"
#include <experimental/filesystem>
#ifdef _MSC_VER
#include <filesystem>
#endif
#include "core/graph/graph_viewer.h"  //for onnxruntime::NodeArg
#include "utils.h"
#include "testenv.h"
#include "providers.h"

using namespace std::experimental::filesystem::v1;
using onnxruntime::Status;

namespace onnxruntime {
namespace perftest {
Status PerformanceRunner::Run() {
  if (!Initialize()) {
    return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "failed to initialize.");
  }

  // warm up
  RunOneIteration(true /*isWarmup*/);

  if (!performance_test_config_.run_config.profile_file.empty())
    session_object_->StartProfiling(performance_test_config_.run_config.profile_file);

  std::unique_ptr<utils::ICPUUsage> p_ICPUUsage = utils::CreateICPUUsage();
  switch (performance_test_config_.run_config.test_mode) {
    case TestMode::kFixDurationMode:
      ORT_RETURN_IF_ERROR(RunFixDuration());
      break;
    case TestMode::KFixRepeatedTimesMode:
      ORT_RETURN_IF_ERROR(RunRepeatedTimes());
      break;
    default:
      return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "unknown test mode.");
  }
  performance_result_.average_CPU_usage = p_ICPUUsage->GetUsage();
  performance_result_.peak_workingset_size = utils::GetPeakWorkingSetSize();

  if (!performance_test_config_.run_config.profile_file.empty())
    session_object_->EndProfiling();

  std::cout << "Total time cost:" << performance_result_.total_time_cost << std::endl
            << "Total iterations:" << performance_result_.time_costs.size() << std::endl
            << "Average time cost:" << performance_result_.total_time_cost / performance_result_.time_costs.size() * 1000 << " ms" << std::endl;
  return Status::OK();
}

bool PerformanceRunner::Initialize() {
  path model_path(performance_test_config_.model_info.model_file_path);
  if (model_path.extension() != ".onnx") {
    LOGF_DEFAULT(ERROR, "input path is not a valid model");
    return false;
  }

  // TODO: remove the input and model name's dependency on directory tree
  std::string model_name = model_path.parent_path().filename().string();
  if (model_name.compare(0, 5, "test_") == 0) model_name = model_name.substr(5);
  performance_result_.model_name = model_name;

  // TODO: remove dependency on OnnxTestCase.
  std::unique_ptr<ITestCase> test_case(CreateOnnxTestCase(model_name));

  if (!test_case->SetModelPath(model_path).IsOK()) {
    LOGF_DEFAULT(ERROR, "load model failed");
    return false;
  }

  std::vector<std::string> provider_types {
#ifdef USE_MKLDNN
    onnxruntime::kMklDnnExecutionProvider,
#endif
#ifdef USE_CUDA
        onnxruntime::kCudaExecutionProvider,
#endif
#ifdef USE_NUPHAR
        onnxruntime::kNupharExecutionProvider,
#endif
#if USE_BRAINSLICE
        onnxruntime::kBrainSliceExecutionProvider,
#endif
#if USE_TRT
        onnxruntime::kTRTExecutionProvider,
#endif
        onnxruntime::kCpuExecutionProvider
  };

  SessionFactory sf(std::move(provider_types), true, true);
  sf.enable_sequential_execution = performance_test_config_.run_config.enable_sequential_execution;
  sf.session_thread_pool_size = 6;

  sf.Create(session_object_, test_case->GetModelUrl(), test_case->GetTestCaseName());

  // Initialize IO Binding
  if (!session_object_->NewIOBinding(&io_binding_).IsOK()) {
    LOGF_DEFAULT(ERROR, "Failed to init session and IO binding");
    return false;
  }

  auto provider_type = performance_test_config_.machine_config.provider_type_name;
  // Place input tensor on cpu memory if mkldnn provider type to avoid CopyTensor logic in CopyInputAcrossDevices
  // TODO: find a better way to do this.
  if (provider_type == onnxruntime::kMklDnnExecutionProvider) {
    provider_type = onnxruntime::kCpuExecutionProvider;
  }
  AllocatorPtr cpu_allocator = io_binding_->GetCPUAllocator(0, provider_type);
  test_case->SetAllocator(cpu_allocator);

  if (test_case->GetDataCount() <= 0) {
    LOGF_DEFAULT(ERROR, "there is no test data for model %s", test_case->GetTestCaseName().c_str());
    return false;
  }

  std::unordered_map<std::string, ::onnxruntime::MLValue> feeds;
  test_case->LoadTestData(0 /* id */, feeds, true);
  for (auto feed : feeds) {
    io_binding_->BindInput(feed.first, feed.second);
  }
  auto outputs = session_object_->GetModelOutputs();
  auto status = outputs.first;
  if (!outputs.first.IsOK()) {
    LOGF_DEFAULT(ERROR, "GetOutputs failed, TestCaseName:%s, ErrorMessage:%s",
                 test_case->GetTestCaseName().c_str(),
                 status.ErrorMessage().c_str());
    return false;
  }

  std::vector<MLValue> output_mlvalues(outputs.second->size());
  for (size_t i_output = 0; i_output < outputs.second->size(); ++i_output) {
    auto output = outputs.second->at(i_output);
    if (!output) continue;
    io_binding_->BindOutput(output->Name(), output_mlvalues[i_output]);
  }

  return true;
}

}  // namespace perftest

}  // namespace onnxruntime
<commit_msg>Check some return status values that were ignored and add logging of any error messages in onnxruntime_perf_test. (#525)<commit_after>// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#include "performance_runner.h"
#include "TestCase.h"
#include <experimental/filesystem>
#ifdef _MSC_VER
#include <filesystem>
#endif
#include "core/graph/graph_viewer.h"  //for onnxruntime::NodeArg
#include "utils.h"
#include "testenv.h"
#include "providers.h"

using namespace std::experimental::filesystem::v1;
using onnxruntime::Status;

namespace onnxruntime {
namespace perftest {
Status PerformanceRunner::Run() {
  if (!Initialize()) {
    return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "failed to initialize.");
  }

  // warm up
  RunOneIteration(true /*isWarmup*/);

  if (!performance_test_config_.run_config.profile_file.empty())
    session_object_->StartProfiling(performance_test_config_.run_config.profile_file);

  std::unique_ptr<utils::ICPUUsage> p_ICPUUsage = utils::CreateICPUUsage();
  switch (performance_test_config_.run_config.test_mode) {
    case TestMode::kFixDurationMode:
      ORT_RETURN_IF_ERROR(RunFixDuration());
      break;
    case TestMode::KFixRepeatedTimesMode:
      ORT_RETURN_IF_ERROR(RunRepeatedTimes());
      break;
    default:
      return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "unknown test mode.");
  }
  performance_result_.average_CPU_usage = p_ICPUUsage->GetUsage();
  performance_result_.peak_workingset_size = utils::GetPeakWorkingSetSize();

  if (!performance_test_config_.run_config.profile_file.empty())
    session_object_->EndProfiling();

  std::cout << "Total time cost:" << performance_result_.total_time_cost << std::endl
            << "Total iterations:" << performance_result_.time_costs.size() << std::endl
            << "Average time cost:" << performance_result_.total_time_cost / performance_result_.time_costs.size() * 1000 << " ms" << std::endl;
  return Status::OK();
}

bool PerformanceRunner::Initialize() {
  path model_path(performance_test_config_.model_info.model_file_path);
  if (model_path.extension() != ".onnx") {
    LOGF_DEFAULT(ERROR, "input path is not a valid model");
    return false;
  }

  // TODO: remove the input and model name's dependency on directory tree
  std::string model_name = model_path.parent_path().filename().string();
  if (model_name.compare(0, 5, "test_") == 0) model_name = model_name.substr(5);
  performance_result_.model_name = model_name;

  // TODO: remove dependency on OnnxTestCase.
  std::unique_ptr<ITestCase> test_case(CreateOnnxTestCase(model_name));

  if (!test_case->SetModelPath(model_path).IsOK()) {
    LOGF_DEFAULT(ERROR, "load model failed");
    return false;
  }

  std::vector<std::string> provider_types {
#ifdef USE_MKLDNN
    onnxruntime::kMklDnnExecutionProvider,
#endif
#ifdef USE_CUDA
        onnxruntime::kCudaExecutionProvider,
#endif
#ifdef USE_NUPHAR
        onnxruntime::kNupharExecutionProvider,
#endif
#if USE_BRAINSLICE
        onnxruntime::kBrainSliceExecutionProvider,
#endif
#if USE_TRT
        onnxruntime::kTRTExecutionProvider,
#endif
        onnxruntime::kCpuExecutionProvider
  };

  SessionFactory sf(std::move(provider_types), true, true);
  sf.enable_sequential_execution = performance_test_config_.run_config.enable_sequential_execution;
  sf.session_thread_pool_size = 6;

  auto status = sf.Create(session_object_, test_case->GetModelUrl(), test_case->GetTestCaseName());
  if (!status.IsOK()) {
    LOGS_DEFAULT(ERROR) << "Failed to create InferenceSession."
                        << " TestCaseName:" << test_case->GetTestCaseName()
                        << ", Error:" << status.ErrorMessage();
    return false;
  }

  // Initialize IO Binding
  status = session_object_->NewIOBinding(&io_binding_);
  if (!status.IsOK()) {
    LOGS_DEFAULT(ERROR) << "Failed to init session and IO binding. "
                        << " TestCaseName:" << test_case->GetTestCaseName()
                        << ", Error:" << status.ErrorMessage();
    return false;
  }

  auto provider_type = performance_test_config_.machine_config.provider_type_name;
  // Place input tensor on cpu memory if mkldnn provider type to avoid CopyTensor logic in CopyInputAcrossDevices
  // TODO: find a better way to do this.
  if (provider_type == onnxruntime::kMklDnnExecutionProvider) {
    provider_type = onnxruntime::kCpuExecutionProvider;
  }
  AllocatorPtr cpu_allocator = io_binding_->GetCPUAllocator(0, provider_type);
  test_case->SetAllocator(cpu_allocator);

  if (test_case->GetDataCount() <= 0) {
    LOGS_DEFAULT(ERROR) << "there is no test data for model ", test_case->GetTestCaseName();
    return false;
  }

  std::unordered_map<std::string, ::onnxruntime::MLValue> feeds;
  test_case->LoadTestData(0 /* id */, feeds, true);
  for (auto feed : feeds) {
    status = io_binding_->BindInput(feed.first, feed.second);
    if (!status.IsOK()) {
      LOGS_DEFAULT(ERROR) << "BindInput failed for " << feed.first
                          << " TestCaseName:" << test_case->GetTestCaseName()
                          << ", Error:" << status.ErrorMessage();
      return false;
    }
  }

  auto outputs = session_object_->GetModelOutputs();
  status = outputs.first;
  if (!status.IsOK()) {
    LOGS_DEFAULT(ERROR) << "GetOutputs failed. TestCaseName:" << test_case->GetTestCaseName()
                        << ", Error:" << status.ErrorMessage();
    return false;
  }

  std::vector<MLValue> output_mlvalues(outputs.second->size());
  for (size_t i_output = 0; i_output < outputs.second->size(); ++i_output) {
    auto output = outputs.second->at(i_output);
    if (!output) continue;
    status = io_binding_->BindOutput(output->Name(), output_mlvalues[i_output]);
    if (!status.IsOK()) {
      LOGS_DEFAULT(ERROR) << "BindOutput failed for " << output->Name()
                          << " TestCaseName:" << test_case->GetTestCaseName()
                          << ", Error:" << status.ErrorMessage();
      return false;
    }
  }

  return true;
}

}  // namespace perftest

}  // namespace onnxruntime
<|endoftext|>


<commit_before>/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/

#ifndef OOX_DRAWINGML_TABLEPROPERTIES_HXX
#define OOX_DRAWINGML_TABLEPROPERTIES_HXX

#include "oox/drawingml/table/tablerow.hxx"
#include "oox/drawingml/table/tablestyle.hxx"
#include "oox/helper/propertymap.hxx"
#include "oox/drawingml/color.hxx"

#include <boost/shared_ptr.hpp>
#include <boost/optional.hpp>
#include <vector>
#include <map>

namespace oox { namespace drawingml { namespace table {

class TableProperties
{
public:

    TableProperties();
    ~TableProperties();

    std::vector< sal_Int32 >& getTableGrid() { return mvTableGrid; };
    std::vector< TableRow >& getTableRows() { return mvTableRows; };

    rtl::OUString&                      getStyleId(){ return maStyleId; };
    boost::shared_ptr< TableStyle >&    getTableStyle(){ return mpTableStyle; };
    sal_Bool&                           isRtl(){ return mbRtl; };
    sal_Bool&                           isFirstRow(){ return mbFirstRow; };
    sal_Bool&                           isFirstCol(){ return mbFirstCol; };
    sal_Bool&                           isLastRow(){ return mbLastRow; };
    sal_Bool&                           isLastCol(){ return mbLastCol; };
    sal_Bool&                           isBandRow(){ return mbBandRow; };
    sal_Bool&                           isBandCol(){ return mbBandCol; };

    void apply( const TablePropertiesPtr& );
    void pushToPropSet( const ::oox::core::XmlFilterBase& rFilterBase,
        const ::com::sun::star::uno::Reference < ::com::sun::star::beans::XPropertySet > & xPropSet, ::oox::drawingml::TextListStylePtr pMasterTextListStyle );

private:

    const TableStyle&                   getUsedTableStyle( const ::oox::core::XmlFilterBase& rFilterBase, sal_Bool &isCreateTabStyle);

    rtl::OUString                       maStyleId;              // either StyleId is available
    boost::shared_ptr< TableStyle >     mpTableStyle;           // or the complete TableStyle
    std::vector< sal_Int32 >            mvTableGrid;
    std::vector< TableRow >             mvTableRows;

    sal_Bool                            mbRtl;
    sal_Bool                            mbFirstRow;
    sal_Bool                            mbFirstCol;
    sal_Bool                            mbLastRow;
    sal_Bool                            mbLastCol;
    sal_Bool                            mbBandRow;
    sal_Bool                            mbBandCol;
};

} } }

#endif  //  OOX_DRAWINGML_TABLEPROPERTIES_HXX
<commit_msg>Don't merge this file<commit_after><|endoftext|>


<commit_before>#pragma once

#include <complex>
#include <cmath>
#include <cassert>

namespace maffs
{
    // returns (mean, stddev)
    template<class InputIt, class T>
    std::pair<float, float>
    estimate_wrapped_normal_distribution(InputIt first, InputIt last, T min, T max)
    {
        assert(std::distance(first, last) > 0);

        std::complex<T> z;
        T r2_cos{};
        T r2_sin{};
        for (auto it = first; it != last; ++it)
        {
            z += std::exp(std::complex<T>(0, *it));
            r2_cos += std::cos(*it);
            r2_sin += std::sin(*it);
        }
        z /= std::distance(first, last);
        auto r2 = std::pow(r2_cos / std::distance(first, last), 2)
                + std::pow(r2_sin / std::distance(first, last), 2);
        auto variance = std::log(1.0f / r2);

        auto mu = std::log(z).imag();

        return {mu, std::sqrt(variance)};
    }

    // returns (mean, stddev)
    template<class InputIt, class T>
    std::pair<float, float>
    estimate_normal_distribution(InputIt first, InputIt last)
    {
        assert(std::distance(first, last) > 0);

        T mean{};
        for (auto it = first; it != last; ++it)
        {
            mean += *it;
        }
        mean /= std::distance(first, last);

        T variance{};
        for (auto it = first; it != last; ++it)
        {
            variance += std::pow(*it - mean, 2);
        }
        variance /= std::distance(first, last);

        return {mean, std::sqrt(variance)};
    }
}
<commit_msg>fix template deduction<commit_after>#pragma once

#include <complex>
#include <cmath>
#include <cassert>

namespace maffs
{
    // returns (mean, stddev)
    template<class InputIt, class T = typename std::iterator_traits<InputIt>::value_type>
    std::pair<float, float>
    estimate_wrapped_normal_distribution(InputIt first, InputIt last, T min, T max)
    {
        assert(std::distance(first, last) > 0);

        std::complex<T> z;
        T r2_cos{};
        T r2_sin{};
        for (auto it = first; it != last; ++it)
        {
            z += std::exp(std::complex<T>(0, *it));
            r2_cos += std::cos(*it);
            r2_sin += std::sin(*it);
        }
        z /= std::distance(first, last);
        auto r2 = std::pow(r2_cos / std::distance(first, last), 2)
                + std::pow(r2_sin / std::distance(first, last), 2);
        auto variance = std::log(1.0f / r2);

        auto mu = std::log(z).imag();

        return {mu, std::sqrt(variance)};
    }

    // returns (mean, stddev)
    template<class InputIt, class T = typename std::iterator_traits<InputIt>::value_type>
    std::pair<float, float>
    estimate_normal_distribution(InputIt first, InputIt last)
    {
        assert(std::distance(first, last) > 0);

        T mean{};
        for (auto it = first; it != last; ++it)
        {
            mean += *it;
        }
        mean /= std::distance(first, last);

        T variance{};
        for (auto it = first; it != last; ++it)
        {
            variance += std::pow(*it - mean, 2);
        }
        variance /= std::distance(first, last);

        return {mean, std::sqrt(variance)};
    }
}
<|endoftext|>