<commit_before>#include <Python.h>
#include <string>
#include <vector>

#include "cc/misc/unicode.h"
#include "cc/analysis/analyzer.h"

using std::string;
using std::vector;

namespace {

char PHRASER_DOC[] =
    "Python extension that detects phrases in text.\n";

Analyzer* ANALYZER = NULL;

char INIT_DOC[] =
    "phrase config texts -> error str or None.\n"
    "\n"
    "Initialize the module.  Must call this first.\n"
    "\n"
    "    >>> open('plaudit.txt', 'wb').write('\\n'.join([\n"
    "            'plaudit = verb object',\n"
    "            '----------',\n"
    "            'thanks',\n"
    "            '----------',\n"
    "            'obama',\n"
    "            'hitler',\n"
    "        ]))\n"
    "    >>> phrases_config_ff = ['plaudit.txt']\n"
    "    >>> phrase_configs = map(lambda f: open(f).read(), phrase_config_ff)\n"
    "    >>> err = _phraser.init(phrase_configs)\n"
    "    >>> assert not err\n";

PyObject* Init(PyObject* self, PyObject* args) {
    // Get args.
    PyObject* list;
    if (!PyArg_ParseTuple(args, "O!", &PyList_Type, &list)) {
        return NULL;
    }

    // Extract phrase configs from list.
    vector<string> phrase_configs;
    Py_ssize_t length = PyList_Size(list);
    for (Py_ssize_t i = 0; i < length; ++i) {
        PyObject* s = PyList_GetItem(list, i);
        if (!PyString_Check(s)) {
            return PyUnicode_FromFormat(
                "[Phraser] List item at index %ld was not a string.", i);
        }
        phrase_configs.emplace_back(PyString_AsString(s));
    }

    // Allocate the Analyzer.
    if (!ANALYZER) {
        ANALYZER = new Analyzer();
    }

    // Call Init().
    string error;
    if (!ANALYZER->Init(phrase_configs, &error)) {
        return PyUnicode_FromString(error.data());
    }

    return Py_None;
}

char TO_D_DOC[] =
    "-> dict.\n"
    "\n"
    "Dump my state as a recursive dict.\n"
    "\n"
    "You can call phrase_detector_json_to_html.py to visualize the output as\n"
    "pretty HTML.\n"
    "\n"
    "    >>> d = _phraser.to_d()\n"

PyObject* ToD(PyObject* self, PyObject* args) {
    return NULL;
}

char ANALYZE_DOC[] =
    "text, options -> phrase detection result dict, error str.\n"
    "\n"
    "Analyze the text.  Returns a pair.  Either the results dict or the \n"
    "error str will be None.\n"
    "\n"
    "    >>> text = u'This is a comment.'\n"
    "    >>> options = {\n"
    "            'destutter_max_consecutive': 3,\n"
    "            'replace_html_entities': True,\n"
    "        }\n"
    "    >>> err = _phraser.analyze(text, options)\n"
    "    >>> assert not err\n";

bool AnalysisOptionsFromDict(
        PyObject* obj, AnalysisOptions* options, string* error) {
    Py_ssize_t pos = 0;
    PyObject* key;
    PyObject* value;
    while (PyDict_Next(obj, &pos, &key, &value)) {
        if (!PyString_Check(key)) {
            *error = "[Phraser] Analysis options key is not a string.";
            return false;
        }
        const char* key_s = PyString_AsString(key);
        if (!strcmp(key_s, "destutter_max_consecutive")) {
            if (!PyInt_Check(value)) {
                *error = "[Phraser] Analysis option "
                         "'destutter_max_consecutive' is an integer.";
                return false;
            }
            Py_ssize_t size = PyInt_AsSsize_t(value);
            options->destutter_max_consecutive = static_cast<size_t>(size);
        } else if (!strcmp(key_s, "replace_html_entities")) {
            if (!PyBool_Check(value)) {
                *error = "[Phraser] Analysis option 'replace_html_entities' is "
                         "a bool.";
                return false;
            }
            options->replace_html_entities = PyObject_IsTrue(value);
        } else {
            *error = "[Phraser] Unknown analysis option.";
            return false;
        }
    }
    return true;
}

PyObject* UnicodeFromUstring(const ustring& s) {
#ifdef Py_UNICODE_WIDE
    // UCS 4 (eg, Linux).
    return PyUnicode_FromUnicode(s.data(), s.size());
#else
    // UCS 2 (eg, Mac OS X).
    vector<Py_UNICODE> v;
    for (auto& c : s) {
        v.emplace_back(static_cast<Py_UNICODE>(c));
    }
    return PyUnicode_FromUnicode(v.data(), v.size());
#endif
}

PyObject* MakeDict(const vector<PyObject*>& keys,
                   const vector<PyObject*>& values) {
    if (keys.size() != values.size()) {
        return NULL;
    }

    PyObject* d = PyDict_New();
    for (auto i = 0u; i < keys.size(); ++i) {
        PyObject* k = keys[i];
        PyObject* v = values[i];
        if (!k) {
            return NULL;
        }
        if (!v) {
            return NULL;
        }
        if (PyDict_SetItem(d, k, v)) {
            return NULL;
        }
    }

    return d;
}

// Returned dicts look like
//
// {
//     'original_text':  'Some texxxxxxxt',
//     'clean_text':     'Some texxxt',
//     'tokens':         ['some', 'text'],
//     'phrase_results': [...],
// }
//
// where 'phrase_results' is a list like
//
// {
//     'phrase_name': 'threat_statement',
//     'subsequence_names': ['subject', 'aux', 'verb'],
//     'index_lists': [...]
// }
PyObject* DictFromAnalysisResult(const AnalysisResult& result, string* error) {
    PyObject* key;
    PyObject* value;
    vector<PyObject*> keys;
    vector<PyObject*> values;

    key = PyString_FromString("original_text");
    value = UnicodeFromUstring(result.original_text);
    keys.emplace_back(key);
    values.emplace_back(value);

    key = PyString_FromString("clean_text");
    value = UnicodeFromUstring(result.clean_text);
    keys.emplace_back(key);
    values.emplace_back(value);

    key = PyString_FromString("tokens");
    value = PyList_New(result.tokens.size());
    for (auto i = 0u; i < result.tokens.size(); ++i) {
        PyObject* token = PyString_FromString(result.tokens[i].data());
        PyList_SET_ITEM(value, i, token);
    }
    keys.emplace_back(key);
    values.emplace_back(value);

    key = PyString_FromString("phrase_matches");
    value = PyList_New(result.phrase_results.size());
    for (auto i = 0u; i < result.phrase_results.size(); ++i) {
        auto& phrase_result = result.phrase_results[i];

        vector<PyObject*> tmp_keys;
        vector<PyObject*> tmp_values;

        PyObject* tmp_key = PyString_FromString("phrase_name");
        PyObject* tmp_value = PyString_FromString(
            phrase_result.phrase_name.data());
        tmp_keys.emplace_back(tmp_key);
        tmp_values.emplace_back(tmp_value);

        tmp_key = PyString_FromString("subsequence_names");
        tmp_value = PyList_New(phrase_result.piece_names.size());
        for (auto j = 0u; j < phrase_result.piece_names.size(); ++j) {
            PyObject* subsequence_name =
                PyString_FromString(phrase_result.piece_names[j].data());
            PyList_SET_ITEM(tmp_value, j, subsequence_name);
        }
        tmp_keys.emplace_back(tmp_key);
        tmp_values.emplace_back(tmp_value);

        tmp_key = PyString_FromString("index_lists");
        tmp_value = PyList_New(phrase_result.matches.size());
        for (auto j = 0u; j < phrase_result.matches.size(); ++j) {
            auto& match = phrase_result.matches[j];
            PyObject* index_list = PyList_New(
                match.piece_begin_indexes.size() + 1);
            for (auto k = 0u; k < match.piece_begin_indexes.size(); ++k) {
                PyObject* item = PyInt_FromLong(match.piece_begin_indexes[k]);
                PyList_SET_ITEM(index_list, k, item);
            }
            PyObject* item = PyInt_FromLong(match.end_excl);
            PyList_SET_ITEM(index_list, match.piece_begin_indexes.size(), item);
            PyList_SET_ITEM(tmp_value, j, index_list);
        }
        tmp_keys.emplace_back(tmp_key);
        tmp_values.emplace_back(tmp_value);

        PyObject* tmp_d = MakeDict(tmp_keys, tmp_values);
        PyList_SET_ITEM(value, i, tmp_d);
    }
    keys.emplace_back(key);
    values.emplace_back(value);

    return MakeDict(keys, values);
}

PyObject* MakeTuple(PyObject* first, PyObject* second) {
    PyObject* r = PyTuple_New(2);
    PyTuple_SetItem(r, 0, first);
    PyTuple_SetItem(r, 1, second);
    return r;
}

PyObject* Analyze(PyObject* self, PyObject* args) {
    // Get args.
    PyObject* py_text;
    PyObject* options_dict;
    if (!PyArg_ParseTuple(args, "UO!", &py_text, &PyDict_Type, &options_dict)) {
        return NULL;
    }

    // Check if initialized.
    if (!ANALYZER) {
        return MakeTuple(
            Py_None, PyUnicode_FromString("[Phraser] Call init() first."));
    }

    // Get the input text to analyze.
    ustring text;
    Py_ssize_t size = PyUnicode_GetSize(py_text);
    for (Py_ssize_t i = 0; i < size; ++i) {
        text.emplace_back(PyUnicode_AsUnicode(py_text)[i]);
    }

    // Set the analysis options.
    AnalysisOptions options;
    string error;
    if (!AnalysisOptionsFromDict(options_dict, &options, &error)) {
        return MakeTuple(
            Py_None, PyUnicode_FromString(error.data()));
    }

    // Analyze the text.
    AnalysisResult result;
    if (!ANALYZER->Analyze(text, options, &result, &error)) {
        return MakeTuple(
            Py_None, PyUnicode_FromString(error.data()));
    }

    // Convert the results to a python dict.
    PyObject* result_dict;
    if (!(result_dict = DictFromAnalysisResult(result, &error))) {
        return MakeTuple(
            Py_None, PyUnicode_FromString(error.data()));
    }

    return MakeTuple(result_dict, Py_None);
}

PyMethodDef PHRASER_METHODS[] = {
    {"init",    Init,    METH_VARARGS, INIT_DOC},
    {"to_d",    ToD,     METH_VARARGS, TO_D_DOC},
    {"analyze", Analyze, METH_VARARGS, ANALYZE_DOC},
    {nullptr,   nullptr, 0,            nullptr},
};

}  // namespace

extern "C" void initphraser(void);

PyMODINIT_FUNC initphraser(void) {
    Py_InitModule3("phraser", PHRASER_METHODS, PHRASER_DOC);
}
<commit_msg>to_d() -> to_dict().<commit_after>#include <Python.h>
#include <string>
#include <vector>

#include "cc/misc/unicode.h"
#include "cc/analysis/analyzer.h"

using std::string;
using std::vector;

namespace {

char PHRASER_DOC[] =
    "Python extension that detects phrases in text.\n";

Analyzer* ANALYZER = NULL;

char INIT_DOC[] =
    "phrase config texts -> error str or None.\n"
    "\n"
    "Initialize the module.  Must call this first.\n"
    "\n"
    "    >>> open('plaudit.txt', 'wb').write('\\n'.join([\n"
    "            'plaudit = verb object',\n"
    "            '----------',\n"
    "            'thanks',\n"
    "            '----------',\n"
    "            'obama',\n"
    "            'hitler',\n"
    "        ]))\n"
    "    >>> phrases_config_ff = ['plaudit.txt']\n"
    "    >>> phrase_configs = map(lambda f: open(f).read(), phrase_config_ff)\n"
    "    >>> err = _phraser.init(phrase_configs)\n"
    "    >>> assert not err\n";

PyObject* Init(PyObject* self, PyObject* args) {
    // Get args.
    PyObject* list;
    if (!PyArg_ParseTuple(args, "O!", &PyList_Type, &list)) {
        return NULL;
    }

    // Extract phrase configs from list.
    vector<string> phrase_configs;
    Py_ssize_t length = PyList_Size(list);
    for (Py_ssize_t i = 0; i < length; ++i) {
        PyObject* s = PyList_GetItem(list, i);
        if (!PyString_Check(s)) {
            return PyUnicode_FromFormat(
                "[Phraser] List item at index %ld was not a string.", i);
        }
        phrase_configs.emplace_back(PyString_AsString(s));
    }

    // Allocate the Analyzer.
    if (!ANALYZER) {
        ANALYZER = new Analyzer();
    }

    // Call Init().
    string error;
    if (!ANALYZER->Init(phrase_configs, &error)) {
        return PyUnicode_FromString(error.data());
    }

    return Py_None;
}

char TO_D_DOC[] =
    "-> dict.\n"
    "\n"
    "Dump my state as a recursive dict.\n"
    "\n"
    "You can call phrase_detector_json_to_html.py to visualize the output as\n"
    "pretty HTML.\n"
    "\n"
    "    >>> d = _phraser.to_dict()\n"

PyObject* ToDict(PyObject* self, PyObject* args) {
    return PyDict_New();  // TODO
}

char ANALYZE_DOC[] =
    "text, options -> phrase detection result dict, error str.\n"
    "\n"
    "Analyze the text.  Returns a pair.  Either the results dict or the \n"
    "error str will be None.\n"
    "\n"
    "    >>> text = u'This is a comment.'\n"
    "    >>> options = {\n"
    "            'destutter_max_consecutive': 3,\n"
    "            'replace_html_entities': True,\n"
    "        }\n"
    "    >>> err = _phraser.analyze(text, options)\n"
    "    >>> assert not err\n";

bool AnalysisOptionsFromDict(
        PyObject* obj, AnalysisOptions* options, string* error) {
    Py_ssize_t pos = 0;
    PyObject* key;
    PyObject* value;
    while (PyDict_Next(obj, &pos, &key, &value)) {
        if (!PyString_Check(key)) {
            *error = "[Phraser] Analysis options key is not a string.";
            return false;
        }
        const char* key_s = PyString_AsString(key);
        if (!strcmp(key_s, "destutter_max_consecutive")) {
            if (!PyInt_Check(value)) {
                *error = "[Phraser] Analysis option "
                         "'destutter_max_consecutive' is an integer.";
                return false;
            }
            Py_ssize_t size = PyInt_AsSsize_t(value);
            options->destutter_max_consecutive = static_cast<size_t>(size);
        } else if (!strcmp(key_s, "replace_html_entities")) {
            if (!PyBool_Check(value)) {
                *error = "[Phraser] Analysis option 'replace_html_entities' is "
                         "a bool.";
                return false;
            }
            options->replace_html_entities = PyObject_IsTrue(value);
        } else {
            *error = "[Phraser] Unknown analysis option.";
            return false;
        }
    }
    return true;
}

PyObject* UnicodeFromUstring(const ustring& s) {
#ifdef Py_UNICODE_WIDE
    // UCS 4 (eg, Linux).
    return PyUnicode_FromUnicode(s.data(), s.size());
#else
    // UCS 2 (eg, Mac OS X).
    vector<Py_UNICODE> v;
    for (auto& c : s) {
        v.emplace_back(static_cast<Py_UNICODE>(c));
    }
    return PyUnicode_FromUnicode(v.data(), v.size());
#endif
}

PyObject* MakeDict(const vector<PyObject*>& keys,
                   const vector<PyObject*>& values) {
    if (keys.size() != values.size()) {
        return NULL;
    }

    PyObject* d = PyDict_New();
    for (auto i = 0u; i < keys.size(); ++i) {
        PyObject* k = keys[i];
        PyObject* v = values[i];
        if (!k) {
            return NULL;
        }
        if (!v) {
            return NULL;
        }
        if (PyDict_SetItem(d, k, v)) {
            return NULL;
        }
    }

    return d;
}

// Returned dicts look like
//
// {
//     'original_text':  'Some texxxxxxxt',
//     'clean_text':     'Some texxxt',
//     'tokens':         ['some', 'text'],
//     'phrase_results': [...],
// }
//
// where 'phrase_results' is a list like
//
// {
//     'phrase_name': 'threat_statement',
//     'subsequence_names': ['subject', 'aux', 'verb'],
//     'index_lists': [...]
// }
PyObject* DictFromAnalysisResult(const AnalysisResult& result, string* error) {
    PyObject* key;
    PyObject* value;
    vector<PyObject*> keys;
    vector<PyObject*> values;

    key = PyString_FromString("original_text");
    value = UnicodeFromUstring(result.original_text);
    keys.emplace_back(key);
    values.emplace_back(value);

    key = PyString_FromString("clean_text");
    value = UnicodeFromUstring(result.clean_text);
    keys.emplace_back(key);
    values.emplace_back(value);

    key = PyString_FromString("tokens");
    value = PyList_New(result.tokens.size());
    for (auto i = 0u; i < result.tokens.size(); ++i) {
        PyObject* token = PyString_FromString(result.tokens[i].data());
        PyList_SET_ITEM(value, i, token);
    }
    keys.emplace_back(key);
    values.emplace_back(value);

    key = PyString_FromString("phrase_matches");
    value = PyList_New(result.phrase_results.size());
    for (auto i = 0u; i < result.phrase_results.size(); ++i) {
        auto& phrase_result = result.phrase_results[i];

        vector<PyObject*> tmp_keys;
        vector<PyObject*> tmp_values;

        PyObject* tmp_key = PyString_FromString("phrase_name");
        PyObject* tmp_value = PyString_FromString(
            phrase_result.phrase_name.data());
        tmp_keys.emplace_back(tmp_key);
        tmp_values.emplace_back(tmp_value);

        tmp_key = PyString_FromString("subsequence_names");
        tmp_value = PyList_New(phrase_result.piece_names.size());
        for (auto j = 0u; j < phrase_result.piece_names.size(); ++j) {
            PyObject* subsequence_name =
                PyString_FromString(phrase_result.piece_names[j].data());
            PyList_SET_ITEM(tmp_value, j, subsequence_name);
        }
        tmp_keys.emplace_back(tmp_key);
        tmp_values.emplace_back(tmp_value);

        tmp_key = PyString_FromString("index_lists");
        tmp_value = PyList_New(phrase_result.matches.size());
        for (auto j = 0u; j < phrase_result.matches.size(); ++j) {
            auto& match = phrase_result.matches[j];
            PyObject* index_list = PyList_New(
                match.piece_begin_indexes.size() + 1);
            for (auto k = 0u; k < match.piece_begin_indexes.size(); ++k) {
                PyObject* item = PyInt_FromLong(match.piece_begin_indexes[k]);
                PyList_SET_ITEM(index_list, k, item);
            }
            PyObject* item = PyInt_FromLong(match.end_excl);
            PyList_SET_ITEM(index_list, match.piece_begin_indexes.size(), item);
            PyList_SET_ITEM(tmp_value, j, index_list);
        }
        tmp_keys.emplace_back(tmp_key);
        tmp_values.emplace_back(tmp_value);

        PyObject* tmp_d = MakeDict(tmp_keys, tmp_values);
        PyList_SET_ITEM(value, i, tmp_d);
    }
    keys.emplace_back(key);
    values.emplace_back(value);

    return MakeDict(keys, values);
}

PyObject* MakeTuple(PyObject* first, PyObject* second) {
    PyObject* r = PyTuple_New(2);
    PyTuple_SetItem(r, 0, first);
    PyTuple_SetItem(r, 1, second);
    return r;
}

PyObject* Analyze(PyObject* self, PyObject* args) {
    // Get args.
    PyObject* py_text;
    PyObject* options_dict;
    if (!PyArg_ParseTuple(args, "UO!", &py_text, &PyDict_Type, &options_dict)) {
        return NULL;
    }

    // Check if initialized.
    if (!ANALYZER) {
        return MakeTuple(
            Py_None, PyUnicode_FromString("[Phraser] Call init() first."));
    }

    // Get the input text to analyze.
    ustring text;
    Py_ssize_t size = PyUnicode_GetSize(py_text);
    for (Py_ssize_t i = 0; i < size; ++i) {
        text.emplace_back(PyUnicode_AsUnicode(py_text)[i]);
    }

    // Set the analysis options.
    AnalysisOptions options;
    string error;
    if (!AnalysisOptionsFromDict(options_dict, &options, &error)) {
        return MakeTuple(
            Py_None, PyUnicode_FromString(error.data()));
    }

    // Analyze the text.
    AnalysisResult result;
    if (!ANALYZER->Analyze(text, options, &result, &error)) {
        return MakeTuple(
            Py_None, PyUnicode_FromString(error.data()));
    }

    // Convert the results to a python dict.
    PyObject* result_dict;
    if (!(result_dict = DictFromAnalysisResult(result, &error))) {
        return MakeTuple(
            Py_None, PyUnicode_FromString(error.data()));
    }

    return MakeTuple(result_dict, Py_None);
}

PyMethodDef PHRASER_METHODS[] = {
    {"init",    Init,    METH_VARARGS, INIT_DOC},
    {"to_dict", ToDict,  METH_VARARGS, TO_D_DOC},
    {"analyze", Analyze, METH_VARARGS, ANALYZE_DOC},
    {nullptr,   nullptr, 0,            nullptr},
};

}  // namespace

extern "C" void initphraser(void);

PyMODINIT_FUNC initphraser(void) {
    Py_InitModule3("phraser", PHRASER_METHODS, PHRASER_DOC);
}
<|endoftext|>


<commit_before>// Time:  O(n)
// Space: O(1)

class Solution {
public:
    /**
     * @param nums: a vector of integers
     * @param s: an integer
     * @return: an integer representing the minimum size of subarray
     */
    int minimumSize(vector<int> &nums, int s) {
        int start = -1, sum = 0, min_size = INT_MAX;
        for (int i = 0; i < nums.size(); ++i) {
            sum += nums[i];
            while (sum >= s) {
                min_size = min(min_size, i - start);
                sum -= nums[++start];
            }
        }
        if (min_size == INT_MAX) {
            return 0;
        }
        return min_size;
    }
};

// Time:  O(nlogn)
// Space: O(n)
// Binary search solution.
class Solution2 {
public:
    /**
     * @param nums: a vector of integers
     * @param s: an integer
     * @return: an integer representing the minimum size of subarray
     */
    int minimumSize(vector<int> &nums, int s) {
        int min_size = INT_MAX;
        vector<int> sum_from_start(nums.size());
        partial_sum(nums.begin(), nums.end(), sum_from_start.begin());
        for (int i = 0; i < nums.size(); ++i) {
            const auto& end_it = lower_bound(sum_from_start.begin() + i,
                                          sum_from_start.end(),
                                          sum_from_start[i] - nums[i] + s);
            int end = static_cast<int>(end_it - sum_from_start.begin());
            if (end_it != sum_from_start.end()) {
                min_size = min(min_size,  end  - i + 1);
            }
        }
        if (min_size == INT_MAX) {
            return 0;
        }
        return min_size;
    }
};
<commit_msg>Update minimum-size-subarray-sum.cpp<commit_after>// Time:  O(n)
// Space: O(1)

// Sliding window solution.
class Solution {
public:
    /**
     * @param nums: a vector of integers
     * @param s: an integer
     * @return: an integer representing the minimum size of subarray
     */
    int minimumSize(vector<int> &nums, int s) {
        int start = -1, sum = 0, min_size = INT_MAX;
        for (int i = 0; i < nums.size(); ++i) {
            sum += nums[i];
            while (sum >= s) {
                min_size = min(min_size, i - start);
                sum -= nums[++start];
            }
        }
        if (min_size == INT_MAX) {
            return 0;
        }
        return min_size;
    }
};

// Time:  O(nlogn)
// Space: O(n)
// Binary search solution.
class Solution2 {
public:
    /**
     * @param nums: a vector of integers
     * @param s: an integer
     * @return: an integer representing the minimum size of subarray
     */
    int minimumSize(vector<int> &nums, int s) {
        int min_size = INT_MAX;
        vector<int> sum_from_start(nums.size());
        partial_sum(nums.begin(), nums.end(), sum_from_start.begin());
        for (int i = 0; i < nums.size(); ++i) {
            const auto& end_it = lower_bound(sum_from_start.begin() + i,
                                          sum_from_start.end(),
                                          sum_from_start[i] - nums[i] + s);
            int end = static_cast<int>(end_it - sum_from_start.begin());
            if (end_it != sum_from_start.end()) {
                min_size = min(min_size,  end  - i + 1);
            }
        }
        if (min_size == INT_MAX) {
            return 0;
        }
        return min_size;
    }
};
<|endoftext|>


<commit_before>#ifndef RECURSE_ROUTER_HPP
#define RECURSE_ROUTER_HPP

#include <recurse.hpp>
#include <QString>
#include <QHash>
#include <QList>
#include <QPair>
#include <QRegularExpression>

namespace Module
{
    class Router
    {
    private:
        bool m_debug = false;

        void debug(QString message)
        {
            if (m_debug)
                std::cout << "(router debug) " << message.toStdString() << std::endl;
        }

        using HTTP_Method = QList<QPair<QString, Downstream>>;

        HTTP_Method HTTP_GET;
        HTTP_Method HTTP_PUT;
        HTTP_Method HTTP_POST;
        HTTP_Method HTTP_PATCH;
        HTTP_Method HTTP_DELETE;
        HTTP_Method HTTP_HEAD;
        HTTP_Method HTTP_OPTIONS;

        QHash<QString, HTTP_Method*> methods{
           { "GET", &HTTP_GET },
           { "PUT", &HTTP_PUT },
           { "POST", &HTTP_POST },
           { "PATCH", &HTTP_PATCH },
           { "DELETE", &HTTP_DELETE },
           { "HEAD", &HTTP_HEAD },
           { "OPTIONS", &HTTP_OPTIONS },
        };

        // https://tools.ietf.org/html/rfc3986#appendix-A
        QString path_to_regexp(QString path)
        {
            path.prepend("^");

            auto colon = path.indexOf(":");
            if(colon != -1)
            {
                auto question = path.indexOf("?", colon);
                if(question != -1)
                    path.replace(QRegularExpression("/:[A-z0-9]+\\?"), "(?:/([^/]+?))?(?:/(?=$))?");
                else
                    path.replace(QRegularExpression(":[A-z0-9]+"), "[^/]+?");
            }

            auto asterix = path.indexOf("*");
            if(asterix != -1)
                path.insert(asterix, ".");

            path.append("$");

            return path;
        }

    public:

        Router()
        {
            QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
            QRegExp debug_strings("(router)");

            if (debug_strings.indexIn(env.value("DEBUG")) != -1)
                m_debug = true;
        }

        void GET(QString path, Downstream next)
        {
            HTTP_GET.append(QPair<QString, Downstream>(path, next));
        }

        void PUT(QString path, Downstream next)
        {
            HTTP_PUT.append(QPair<QString, Downstream>(path, next));
        }

        void POST(QString path, Downstream next)
        {
            HTTP_POST.append(QPair<QString, Downstream>(path, next));
        }

        void PATCH(QString path, Downstream next)
        {
            HTTP_PATCH.append(QPair<QString, Downstream>(path, next));
        }

        void HEAD(QString path, Downstream next)
        {
            HTTP_HEAD.append(QPair<QString, Downstream>(path, next));
        }

        void DELETE(QString path, Downstream next)
        {
            HTTP_DELETE.append(QPair<QString, Downstream>(path, next));
        }

        void OPTIONS(QString path, Downstream next)
        {
            HTTP_OPTIONS.append(QPair<QString, Downstream>(path, next));
        }

        void ALL(QString path, Downstream next)
        {
           GET(path, next);
           PUT(path, next);
           POST(path, next);
           PATCH(path, next);
           HEAD(path, next);
           DELETE(path, next);
           OPTIONS(path, next);
        }

        auto routes()
        {
            return [this](auto &ctx, auto next)
            {
                auto request = ctx.request;

                if(!methods.contains(request.method))
                    return next();

                auto method = *(methods[request.method]);

                auto url = request.url;
                auto query = url.query();
                auto path = url.path();

                // call first route that matches
                for(auto pair : method)
                {
                    auto key = pair.first;

                    this->debug("trying path:" + key);

                    QRegularExpression regexp(this->path_to_regexp(key));
                    if(!regexp.isValid() || !regexp.match(path).hasMatch())
                        continue;

                    this->debug("path matched");

                    // parse parameters if any
                    auto colon = key.indexOf(":");
                    if(colon)
                    {
                        // we use QStringRef so we don't allocate on search
                        auto matchString = key.midRef(colon);
                        auto pathString = path.midRef(colon);

                        auto matches = matchString.split("/");
                        auto paths = pathString.split("/");

                        // match: /hello/:id/:/name
                        // request: /hello/1/test

                        for(int i = 0; i < matches.size(); i++)
                        {
                            auto match = matches.at(i);
                            colon = match.indexOf(":");
                            if(colon == -1)
                                continue;

                            auto paramKey = match.mid(colon + 1, match.indexOf("?") - 1);
                            auto paramValue = paths.at(i);

                            ctx.request.params[paramKey.toString()] = paramValue.toString();
                        }
                    }

                    auto call = pair.second;
                    call(ctx, next);

                    return;
                }

                // call next middleware if nothing matched
                next();
            };
        }
    };
}

#endif // RECURSE_ROUTER_HPP
<commit_msg>clang-format<commit_after>#ifndef RECURSE_ROUTER_HPP
#define RECURSE_ROUTER_HPP

#include <recurse.hpp>
#include <QString>
#include <QHash>
#include <QList>
#include <QPair>
#include <QRegularExpression>

namespace Module
{
    class Router
    {
    private:
        bool m_debug = false;

        void debug(QString message)
        {
            if (m_debug)
                std::cout << "(router debug) " << message.toStdString() << std::endl;
        }

        using HTTP_Method = QList<QPair<QString, Downstream>>;

        HTTP_Method HTTP_GET;
        HTTP_Method HTTP_PUT;
        HTTP_Method HTTP_POST;
        HTTP_Method HTTP_PATCH;
        HTTP_Method HTTP_DELETE;
        HTTP_Method HTTP_HEAD;
        HTTP_Method HTTP_OPTIONS;

        QHash<QString, HTTP_Method *> methods{
            { "GET", &HTTP_GET }, { "PUT", &HTTP_PUT },
            { "POST", &HTTP_POST }, { "PATCH", &HTTP_PATCH },
            { "DELETE", &HTTP_DELETE }, { "HEAD", &HTTP_HEAD },
            { "OPTIONS", &HTTP_OPTIONS },
        };

        // https://tools.ietf.org/html/rfc3986#appendix-A
        QString path_to_regexp(QString path)
        {
            path.prepend("^");

            auto colon = path.indexOf(":");
            if (colon != -1)
            {
                auto question = path.indexOf("?", colon);
                if (question != -1)
                    // optional arguments :name?
                    path.replace(QRegularExpression("/:[A-z0-9]+\\?"),
                    "(?:/([^/]+?))?(?:/(?=$))?");
                else
                    // regular arguments :name
                    path.replace(QRegularExpression(":[A-z0-9]+"), "[^/]+?");
            }

            // catch-all argument /name/*
            auto asterix = path.indexOf("*");
            if (asterix != -1)
                path.insert(asterix, ".");

            path.append("$");

            return path;
        }

    public:
        Router()
        {
            QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
            QRegExp debug_strings("(router)");

            if (debug_strings.indexIn(env.value("DEBUG")) != -1)
                m_debug = true;
        }

        void GET(QString path, Downstream next)
        {
            HTTP_GET.append(QPair<QString, Downstream>(path, next));
        }

        void PUT(QString path, Downstream next)
        {
            HTTP_PUT.append(QPair<QString, Downstream>(path, next));
        }

        void POST(QString path, Downstream next)
        {
            HTTP_POST.append(QPair<QString, Downstream>(path, next));
        }

        void PATCH(QString path, Downstream next)
        {
            HTTP_PATCH.append(QPair<QString, Downstream>(path, next));
        }

        void HEAD(QString path, Downstream next)
        {
            HTTP_HEAD.append(QPair<QString, Downstream>(path, next));
        }

        void DELETE(QString path, Downstream next)
        {
            HTTP_DELETE.append(QPair<QString, Downstream>(path, next));
        }

        void OPTIONS(QString path, Downstream next)
        {
            HTTP_OPTIONS.append(QPair<QString, Downstream>(path, next));
        }

        void ALL(QString path, Downstream next)
        {
            GET(path, next);
            PUT(path, next);
            POST(path, next);
            PATCH(path, next);
            HEAD(path, next);
            DELETE(path, next);
            OPTIONS(path, next);
        }

        auto routes()
        {
            return [this](auto &ctx, auto next)
            {
                auto request = ctx.request;

                if (!methods.contains(request.method))
                    return next();

                auto method = *(methods[request.method]);

                auto url = request.url;
                auto query = url.query();
                auto path = url.path();

                // call first route that matches
                for (auto pair : method)
                {
                    auto key = pair.first;

                    this->debug("trying path:" + key);

                    QRegularExpression regexp(this->path_to_regexp(key));
                    if (!regexp.isValid() || !regexp.match(path).hasMatch())
                        continue;

                    this->debug("path matched");

                    // parse parameters if any
                    auto colon = key.indexOf(":");
                    if (colon)
                    {
                        // we use QStringRef so we don't allocate on search
                        auto matchString = key.midRef(colon);
                        auto pathString = path.midRef(colon);

                        auto matches = matchString.split("/");
                        auto paths = pathString.split("/");

                        // match: /hello/:id/:/name
                        // request: /hello/1/test

                        for (int i = 0; i < matches.size(); i++)
                        {
                            auto match = matches.at(i);
                            colon = match.indexOf(":");
                            if (colon == -1)
                                continue;

                            auto paramKey = match.mid(colon + 1, match.indexOf("?") - 1);
                            auto paramValue = paths.at(i);

                            ctx.request.params[paramKey.toString()] = paramValue.toString();
                        }
                    }

                    auto call = pair.second;
                    call(ctx, next);

                    return;
                }

                // call next middleware if nothing matched
                next();
            };
        }
    };
}

#endif // RECURSE_ROUTER_HPP
<|endoftext|>


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Daniel Gomez Ferro <dgomezferro@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#include "sparse.h"

template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& ref)
{
  typedef typename SparseMatrixType::Index Index;

  const Index rows = ref.rows();
  const Index cols = ref.cols();
  typedef typename SparseMatrixType::Scalar Scalar;
  enum { Flags = SparseMatrixType::Flags };

  double density = std::max(8./(rows*cols), 0.01);
  typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
  typedef Matrix<Scalar,Dynamic,1> DenseVector;
  Scalar eps = 1e-6;

  SparseMatrixType m(rows, cols);
  DenseMatrix refMat = DenseMatrix::Zero(rows, cols);
  DenseVector vec1 = DenseVector::Random(rows);
  Scalar s1 = internal::random<Scalar>();

  std::vector<Vector2i> zeroCoords;
  std::vector<Vector2i> nonzeroCoords;
  initSparse<Scalar>(density, refMat, m, 0, &zeroCoords, &nonzeroCoords);

  if (zeroCoords.size()==0 || nonzeroCoords.size()==0)
    return;

  // test coeff and coeffRef
  for (int i=0; i<(int)zeroCoords.size(); ++i)
  {
    VERIFY_IS_MUCH_SMALLER_THAN( m.coeff(zeroCoords[i].x(),zeroCoords[i].y()), eps );
    if(internal::is_same<SparseMatrixType,SparseMatrix<Scalar,Flags> >::value)
      VERIFY_RAISES_ASSERT( m.coeffRef(zeroCoords[0].x(),zeroCoords[0].y()) = 5 );
  }
  VERIFY_IS_APPROX(m, refMat);

  m.coeffRef(nonzeroCoords[0].x(), nonzeroCoords[0].y()) = Scalar(5);
  refMat.coeffRef(nonzeroCoords[0].x(), nonzeroCoords[0].y()) = Scalar(5);

  VERIFY_IS_APPROX(m, refMat);
  /*
  // test InnerIterators and Block expressions
  for (int t=0; t<10; ++t)
  {
    int j = internal::random<int>(0,cols-1);
    int i = internal::random<int>(0,rows-1);
    int w = internal::random<int>(1,cols-j-1);
    int h = internal::random<int>(1,rows-i-1);

//     VERIFY_IS_APPROX(m.block(i,j,h,w), refMat.block(i,j,h,w));
    for(int c=0; c<w; c++)
    {
      VERIFY_IS_APPROX(m.block(i,j,h,w).col(c), refMat.block(i,j,h,w).col(c));
      for(int r=0; r<h; r++)
      {
//         VERIFY_IS_APPROX(m.block(i,j,h,w).col(c).coeff(r), refMat.block(i,j,h,w).col(c).coeff(r));
      }
    }
//     for(int r=0; r<h; r++)
//     {
//       VERIFY_IS_APPROX(m.block(i,j,h,w).row(r), refMat.block(i,j,h,w).row(r));
//       for(int c=0; c<w; c++)
//       {
//         VERIFY_IS_APPROX(m.block(i,j,h,w).row(r).coeff(c), refMat.block(i,j,h,w).row(r).coeff(c));
//       }
//     }
  }

  for(int c=0; c<cols; c++)
  {
    VERIFY_IS_APPROX(m.col(c) + m.col(c), (m + m).col(c));
    VERIFY_IS_APPROX(m.col(c) + m.col(c), refMat.col(c) + refMat.col(c));
  }

  for(int r=0; r<rows; r++)
  {
    VERIFY_IS_APPROX(m.row(r) + m.row(r), (m + m).row(r));
    VERIFY_IS_APPROX(m.row(r) + m.row(r), refMat.row(r) + refMat.row(r));
  }
  */

    // test insert (inner random)
    {
      DenseMatrix m1(rows,cols);
      m1.setZero();
      SparseMatrixType m2(rows,cols);
      m2.reserve(10);
      for (int j=0; j<cols; ++j)
      {
        for (int k=0; k<rows/2; ++k)
        {
          int i = internal::random<int>(0,rows-1);
          if (m1.coeff(i,j)==Scalar(0))
            m2.insert(i,j) = m1(i,j) = internal::random<Scalar>();
        }
      }
      m2.finalize();
      VERIFY_IS_APPROX(m2,m1);
    }

    // test insert (fully random)
    {
      DenseMatrix m1(rows,cols);
      m1.setZero();
      SparseMatrixType m2(rows,cols);
      m2.reserve(10);
      for (int k=0; k<rows*cols; ++k)
      {
        int i = internal::random<int>(0,rows-1);
        int j = internal::random<int>(0,cols-1);
        if (m1.coeff(i,j)==Scalar(0))
          m2.insert(i,j) = m1(i,j) = internal::random<Scalar>();
      }
      m2.finalize();
      VERIFY_IS_APPROX(m2,m1);
    }

  // test basic computations
  {
    DenseMatrix refM1 = DenseMatrix::Zero(rows, rows);
    DenseMatrix refM2 = DenseMatrix::Zero(rows, rows);
    DenseMatrix refM3 = DenseMatrix::Zero(rows, rows);
    DenseMatrix refM4 = DenseMatrix::Zero(rows, rows);
    SparseMatrixType m1(rows, rows);
    SparseMatrixType m2(rows, rows);
    SparseMatrixType m3(rows, rows);
    SparseMatrixType m4(rows, rows);
    initSparse<Scalar>(density, refM1, m1);
    initSparse<Scalar>(density, refM2, m2);
    initSparse<Scalar>(density, refM3, m3);
    initSparse<Scalar>(density, refM4, m4);

    VERIFY_IS_APPROX(m1+m2, refM1+refM2);
    VERIFY_IS_APPROX(m1+m2+m3, refM1+refM2+refM3);
    VERIFY_IS_APPROX(m3.cwiseProduct(m1+m2), refM3.cwiseProduct(refM1+refM2));
    VERIFY_IS_APPROX(m1*s1-m2, refM1*s1-refM2);

    VERIFY_IS_APPROX(m1*=s1, refM1*=s1);
    VERIFY_IS_APPROX(m1/=s1, refM1/=s1);

    VERIFY_IS_APPROX(m1+=m2, refM1+=refM2);
    VERIFY_IS_APPROX(m1-=m2, refM1-=refM2);

    VERIFY_IS_APPROX(m1.col(0).dot(refM2.row(0)), refM1.col(0).dot(refM2.row(0)));

    refM4.setRandom();
    // sparse cwise* dense
    VERIFY_IS_APPROX(m3.cwiseProduct(refM4), refM3.cwiseProduct(refM4));
//     VERIFY_IS_APPROX(m3.cwise()/refM4, refM3.cwise()/refM4);
  }

  // test transpose
  {
    DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
    SparseMatrixType m2(rows, rows);
    initSparse<Scalar>(density, refMat2, m2);
    VERIFY_IS_APPROX(m2.transpose().eval(), refMat2.transpose().eval());
    VERIFY_IS_APPROX(m2.transpose(), refMat2.transpose());

    VERIFY_IS_APPROX(SparseMatrixType(m2.adjoint()), refMat2.adjoint());
  }

  // test innerVector()
  {
    DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
    SparseMatrixType m2(rows, rows);
    initSparse<Scalar>(density, refMat2, m2);
    int j0 = internal::random(0,rows-1);
    int j1 = internal::random(0,rows-1);
    VERIFY_IS_APPROX(m2.innerVector(j0), refMat2.col(j0));
    VERIFY_IS_APPROX(m2.innerVector(j0)+m2.innerVector(j1), refMat2.col(j0)+refMat2.col(j1));
    //m2.innerVector(j0) = 2*m2.innerVector(j1);
    //refMat2.col(j0) = 2*refMat2.col(j1);
    //VERIFY_IS_APPROX(m2, refMat2);
  }

  // test innerVectors()
  {
    DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
    SparseMatrixType m2(rows, rows);
    initSparse<Scalar>(density, refMat2, m2);
    int j0 = internal::random(0,rows-2);
    int j1 = internal::random(0,rows-2);
    int n0 = internal::random<int>(1,rows-std::max(j0,j1));
    VERIFY_IS_APPROX(m2.innerVectors(j0,n0), refMat2.block(0,j0,rows,n0));
    VERIFY_IS_APPROX(m2.innerVectors(j0,n0)+m2.innerVectors(j1,n0),
                     refMat2.block(0,j0,rows,n0)+refMat2.block(0,j1,rows,n0));
    //m2.innerVectors(j0,n0) = m2.innerVectors(j0,n0) + m2.innerVectors(j1,n0);
    //refMat2.block(0,j0,rows,n0) = refMat2.block(0,j0,rows,n0) + refMat2.block(0,j1,rows,n0);
  }

  // test prune
  {
    SparseMatrixType m2(rows, rows);
    DenseMatrix refM2(rows, rows);
    refM2.setZero();
    int countFalseNonZero = 0;
    int countTrueNonZero = 0;
    for (int j=0; j<m2.outerSize(); ++j)
    {
      m2.startVec(j);
      for (int i=0; i<m2.innerSize(); ++i)
      {
        float x = internal::random<float>(0,1);
        if (x<0.1)
        {
          // do nothing
        }
        else if (x<0.5)
        {
          countFalseNonZero++;
          m2.insertBackByOuterInner(j,i) = Scalar(0);
        }
        else
        {
          countTrueNonZero++;
          m2.insertBackByOuterInner(j,i) = refM2(i,j) = Scalar(1);
        }
      }
    }
    m2.finalize();
    VERIFY(countFalseNonZero+countTrueNonZero == m2.nonZeros());
    VERIFY_IS_APPROX(m2, refM2);
    m2.prune(1);
    VERIFY(countTrueNonZero==m2.nonZeros());
    VERIFY_IS_APPROX(m2, refM2);
  }

  // test sparseView
  {
    DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
    SparseMatrixType m2(rows, rows);
    VERIFY_IS_APPROX(m2.eval(), refMat2.sparseView().eval());
  }
}

void test_sparse_basic()
{
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1( sparse_basic(SparseMatrix<double>(8, 8)) );
    CALL_SUBTEST_2( sparse_basic(SparseMatrix<std::complex<double> >(16, 16)) );
    CALL_SUBTEST_1( sparse_basic(SparseMatrix<double>(33, 33)) );

    CALL_SUBTEST_3( sparse_basic(DynamicSparseMatrix<double>(8, 8)) );
  }
}
<commit_msg>Additional fix to enforce the compiler to use the correct prunning method.<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Daniel Gomez Ferro <dgomezferro@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#include "sparse.h"

template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& ref)
{
  typedef typename SparseMatrixType::Index Index;

  const Index rows = ref.rows();
  const Index cols = ref.cols();
  typedef typename SparseMatrixType::Scalar Scalar;
  enum { Flags = SparseMatrixType::Flags };

  double density = std::max(8./(rows*cols), 0.01);
  typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
  typedef Matrix<Scalar,Dynamic,1> DenseVector;
  Scalar eps = 1e-6;

  SparseMatrixType m(rows, cols);
  DenseMatrix refMat = DenseMatrix::Zero(rows, cols);
  DenseVector vec1 = DenseVector::Random(rows);
  Scalar s1 = internal::random<Scalar>();

  std::vector<Vector2i> zeroCoords;
  std::vector<Vector2i> nonzeroCoords;
  initSparse<Scalar>(density, refMat, m, 0, &zeroCoords, &nonzeroCoords);

  if (zeroCoords.size()==0 || nonzeroCoords.size()==0)
    return;

  // test coeff and coeffRef
  for (int i=0; i<(int)zeroCoords.size(); ++i)
  {
    VERIFY_IS_MUCH_SMALLER_THAN( m.coeff(zeroCoords[i].x(),zeroCoords[i].y()), eps );
    if(internal::is_same<SparseMatrixType,SparseMatrix<Scalar,Flags> >::value)
      VERIFY_RAISES_ASSERT( m.coeffRef(zeroCoords[0].x(),zeroCoords[0].y()) = 5 );
  }
  VERIFY_IS_APPROX(m, refMat);

  m.coeffRef(nonzeroCoords[0].x(), nonzeroCoords[0].y()) = Scalar(5);
  refMat.coeffRef(nonzeroCoords[0].x(), nonzeroCoords[0].y()) = Scalar(5);

  VERIFY_IS_APPROX(m, refMat);
  /*
  // test InnerIterators and Block expressions
  for (int t=0; t<10; ++t)
  {
    int j = internal::random<int>(0,cols-1);
    int i = internal::random<int>(0,rows-1);
    int w = internal::random<int>(1,cols-j-1);
    int h = internal::random<int>(1,rows-i-1);

//     VERIFY_IS_APPROX(m.block(i,j,h,w), refMat.block(i,j,h,w));
    for(int c=0; c<w; c++)
    {
      VERIFY_IS_APPROX(m.block(i,j,h,w).col(c), refMat.block(i,j,h,w).col(c));
      for(int r=0; r<h; r++)
      {
//         VERIFY_IS_APPROX(m.block(i,j,h,w).col(c).coeff(r), refMat.block(i,j,h,w).col(c).coeff(r));
      }
    }
//     for(int r=0; r<h; r++)
//     {
//       VERIFY_IS_APPROX(m.block(i,j,h,w).row(r), refMat.block(i,j,h,w).row(r));
//       for(int c=0; c<w; c++)
//       {
//         VERIFY_IS_APPROX(m.block(i,j,h,w).row(r).coeff(c), refMat.block(i,j,h,w).row(r).coeff(c));
//       }
//     }
  }

  for(int c=0; c<cols; c++)
  {
    VERIFY_IS_APPROX(m.col(c) + m.col(c), (m + m).col(c));
    VERIFY_IS_APPROX(m.col(c) + m.col(c), refMat.col(c) + refMat.col(c));
  }

  for(int r=0; r<rows; r++)
  {
    VERIFY_IS_APPROX(m.row(r) + m.row(r), (m + m).row(r));
    VERIFY_IS_APPROX(m.row(r) + m.row(r), refMat.row(r) + refMat.row(r));
  }
  */

    // test insert (inner random)
    {
      DenseMatrix m1(rows,cols);
      m1.setZero();
      SparseMatrixType m2(rows,cols);
      m2.reserve(10);
      for (int j=0; j<cols; ++j)
      {
        for (int k=0; k<rows/2; ++k)
        {
          int i = internal::random<int>(0,rows-1);
          if (m1.coeff(i,j)==Scalar(0))
            m2.insert(i,j) = m1(i,j) = internal::random<Scalar>();
        }
      }
      m2.finalize();
      VERIFY_IS_APPROX(m2,m1);
    }

    // test insert (fully random)
    {
      DenseMatrix m1(rows,cols);
      m1.setZero();
      SparseMatrixType m2(rows,cols);
      m2.reserve(10);
      for (int k=0; k<rows*cols; ++k)
      {
        int i = internal::random<int>(0,rows-1);
        int j = internal::random<int>(0,cols-1);
        if (m1.coeff(i,j)==Scalar(0))
          m2.insert(i,j) = m1(i,j) = internal::random<Scalar>();
      }
      m2.finalize();
      VERIFY_IS_APPROX(m2,m1);
    }

  // test basic computations
  {
    DenseMatrix refM1 = DenseMatrix::Zero(rows, rows);
    DenseMatrix refM2 = DenseMatrix::Zero(rows, rows);
    DenseMatrix refM3 = DenseMatrix::Zero(rows, rows);
    DenseMatrix refM4 = DenseMatrix::Zero(rows, rows);
    SparseMatrixType m1(rows, rows);
    SparseMatrixType m2(rows, rows);
    SparseMatrixType m3(rows, rows);
    SparseMatrixType m4(rows, rows);
    initSparse<Scalar>(density, refM1, m1);
    initSparse<Scalar>(density, refM2, m2);
    initSparse<Scalar>(density, refM3, m3);
    initSparse<Scalar>(density, refM4, m4);

    VERIFY_IS_APPROX(m1+m2, refM1+refM2);
    VERIFY_IS_APPROX(m1+m2+m3, refM1+refM2+refM3);
    VERIFY_IS_APPROX(m3.cwiseProduct(m1+m2), refM3.cwiseProduct(refM1+refM2));
    VERIFY_IS_APPROX(m1*s1-m2, refM1*s1-refM2);

    VERIFY_IS_APPROX(m1*=s1, refM1*=s1);
    VERIFY_IS_APPROX(m1/=s1, refM1/=s1);

    VERIFY_IS_APPROX(m1+=m2, refM1+=refM2);
    VERIFY_IS_APPROX(m1-=m2, refM1-=refM2);

    VERIFY_IS_APPROX(m1.col(0).dot(refM2.row(0)), refM1.col(0).dot(refM2.row(0)));

    refM4.setRandom();
    // sparse cwise* dense
    VERIFY_IS_APPROX(m3.cwiseProduct(refM4), refM3.cwiseProduct(refM4));
//     VERIFY_IS_APPROX(m3.cwise()/refM4, refM3.cwise()/refM4);
  }

  // test transpose
  {
    DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
    SparseMatrixType m2(rows, rows);
    initSparse<Scalar>(density, refMat2, m2);
    VERIFY_IS_APPROX(m2.transpose().eval(), refMat2.transpose().eval());
    VERIFY_IS_APPROX(m2.transpose(), refMat2.transpose());

    VERIFY_IS_APPROX(SparseMatrixType(m2.adjoint()), refMat2.adjoint());
  }

  // test innerVector()
  {
    DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
    SparseMatrixType m2(rows, rows);
    initSparse<Scalar>(density, refMat2, m2);
    int j0 = internal::random(0,rows-1);
    int j1 = internal::random(0,rows-1);
    VERIFY_IS_APPROX(m2.innerVector(j0), refMat2.col(j0));
    VERIFY_IS_APPROX(m2.innerVector(j0)+m2.innerVector(j1), refMat2.col(j0)+refMat2.col(j1));
    //m2.innerVector(j0) = 2*m2.innerVector(j1);
    //refMat2.col(j0) = 2*refMat2.col(j1);
    //VERIFY_IS_APPROX(m2, refMat2);
  }

  // test innerVectors()
  {
    DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
    SparseMatrixType m2(rows, rows);
    initSparse<Scalar>(density, refMat2, m2);
    int j0 = internal::random(0,rows-2);
    int j1 = internal::random(0,rows-2);
    int n0 = internal::random<int>(1,rows-std::max(j0,j1));
    VERIFY_IS_APPROX(m2.innerVectors(j0,n0), refMat2.block(0,j0,rows,n0));
    VERIFY_IS_APPROX(m2.innerVectors(j0,n0)+m2.innerVectors(j1,n0),
                     refMat2.block(0,j0,rows,n0)+refMat2.block(0,j1,rows,n0));
    //m2.innerVectors(j0,n0) = m2.innerVectors(j0,n0) + m2.innerVectors(j1,n0);
    //refMat2.block(0,j0,rows,n0) = refMat2.block(0,j0,rows,n0) + refMat2.block(0,j1,rows,n0);
  }

  // test prune
  {
    SparseMatrixType m2(rows, rows);
    DenseMatrix refM2(rows, rows);
    refM2.setZero();
    int countFalseNonZero = 0;
    int countTrueNonZero = 0;
    for (int j=0; j<m2.outerSize(); ++j)
    {
      m2.startVec(j);
      for (int i=0; i<m2.innerSize(); ++i)
      {
        float x = internal::random<float>(0,1);
        if (x<0.1)
        {
          // do nothing
        }
        else if (x<0.5)
        {
          countFalseNonZero++;
          m2.insertBackByOuterInner(j,i) = Scalar(0);
        }
        else
        {
          countTrueNonZero++;
          m2.insertBackByOuterInner(j,i) = refM2(i,j) = Scalar(1);
        }
      }
    }
    m2.finalize();
    VERIFY(countFalseNonZero+countTrueNonZero == m2.nonZeros());
    VERIFY_IS_APPROX(m2, refM2);
    m2.prune(Scalar(1));
    VERIFY(countTrueNonZero==m2.nonZeros());
    VERIFY_IS_APPROX(m2, refM2);
  }

  // test sparseView
  {
    DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
    SparseMatrixType m2(rows, rows);
    VERIFY_IS_APPROX(m2.eval(), refMat2.sparseView().eval());
  }
}

void test_sparse_basic()
{
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1( sparse_basic(SparseMatrix<double>(8, 8)) );
    CALL_SUBTEST_2( sparse_basic(SparseMatrix<std::complex<double> >(16, 16)) );
    CALL_SUBTEST_1( sparse_basic(SparseMatrix<double>(33, 33)) );

    CALL_SUBTEST_3( sparse_basic(DynamicSparseMatrix<double>(8, 8)) );
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.

#include "mfem.hpp"
#include "catch.hpp"

using namespace mfem;

namespace doftrans
{

TEST_CASE("DoF Transformations"
          "[ND_TetDofTransformation]")
{
   int p = 4;
   int seed = 123;

   double tol = 1e-13;

   SECTION("Nedelec Tetrahedral Transformations")
   {
      ND_TetDofTransformation T(p);

      Array<int> ori(4);
      ori[0] = 1;
      ori[1] = 3;
      ori[2] = 5;
      ori[3] = 1;

      T.SetFaceOrientations(ori);

      Vector u(T.Width());
      Vector v(T.Width());
      Vector f(T.Width());
      Vector ut(T.Height());
      Vector vt(T.Height());
      Vector ft(T.Height());

      u.Randomize(seed);
      v.Randomize(seed+1);
      f.Randomize(seed+2);

      SECTION("Inverse DoF transformation")
      {
         Vector w(T.Width());

         T.TransformPrimal(u, ut);
         T.InvTransformPrimal(ut, w);

         w -= u;

         REQUIRE(w.Norml2() < tol * u.Norml2());
      }

      SECTION("Inner product with linear form f(u)")
      {
         T.TransformPrimal(u, ut);
         T.TransformDual(f, ft);

         REQUIRE(fabs(f * u - ft * ut) < tol);
      }

      DenseMatrix A(T.Width());
      {
         Vector Ac;
         for (int i=0; i<A.Width(); i++)
         {
            A.GetColumnReference(i, Ac);
            Ac.Randomize(seed+i);
         }
      }

      SECTION("Inner product of two primal vectors")
      {
         DenseMatrix tA(T.Height(), T.Width());
         DenseMatrix At(T.Width(), T.Height());
         DenseMatrix tAt(T.Height());

         T.TransformPrimal(u, ut);
         T.TransformPrimal(v, vt);

         T.TransformDualRows(A, At);
         T.TransformDualCols(A, tA);
         T.TransformDual(A, tAt);

         double uAv = A.InnerProduct(v, u);

         REQUIRE(fabs(uAv -  At.InnerProduct(vt, u )) < tol * fabs(uAv));
         REQUIRE(fabs(uAv -  tA.InnerProduct(v , ut)) < tol * fabs(uAv));
         REQUIRE(fabs(uAv - tAt.InnerProduct(vt, ut)) < tol * fabs(uAv));
      }
      SECTION("Inner product of a primal vector and a dual vector")
      {
         DenseMatrix tA(T.Height(), T.Width());
         DenseMatrix At(T.Width(), T.Height());
         DenseMatrix tAt(T.Height());

         T.TransformDual(f, ft);
         T.TransformPrimal(v, vt);

         T.TransformDualRows(A, At);
         T.TransformPrimalCols(A, tA);
         T.TransformPrimalCols(At, tAt);

         double fAv = A.InnerProduct(v, f);

         REQUIRE(fabs(fAv -  At.InnerProduct(vt, f )) < tol * fabs(fAv));
         REQUIRE(fabs(fAv -  tA.InnerProduct(v , ft)) < tol * fabs(fAv));
         REQUIRE(fabs(fAv - tAt.InnerProduct(vt, ft)) < tol * fabs(fAv));
      }
   }
}

} // namespace doftrans
<commit_msg>Removing unnecessary matrix and vector sizing<commit_after>// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.

#include "mfem.hpp"
#include "catch.hpp"

using namespace mfem;

namespace doftrans
{

TEST_CASE("DoF Transformation Classes"
          "[ND_TetDofTransformation]")
{
   int p = 4;
   int seed = 123;

   double tol = 1e-13;

   SECTION("Nedelec Tetrahedral Transformations")
   {
      ND_TetDofTransformation T(p);

      Array<int> ori(4);
      ori[0] = 1;
      ori[1] = 3;
      ori[2] = 5;
      ori[3] = 1;

      T.SetFaceOrientations(ori);

      Vector u(T.Width());
      Vector v(T.Width());
      Vector f(T.Width());
      Vector ut;
      Vector vt;
      Vector ft;

      u.Randomize(seed);
      v.Randomize(seed+1);
      f.Randomize(seed+2);

      SECTION("Inverse DoF transformation")
      {
         Vector w;

         T.TransformPrimal(u, ut);
         T.InvTransformPrimal(ut, w);

         w -= u;

         REQUIRE(w.Norml2() < tol * u.Norml2());
      }

      SECTION("Inner product with linear form f(v)")
      {
         T.TransformPrimal(v, vt);
         T.TransformDual(f, ft);

         double fv = f * v;

         REQUIRE(fabs(fv - ft * vt) < tol * fabs(fv));
      }

      DenseMatrix A(T.Width());
      {
         Vector Ac;
         for (int i=0; i<A.Width(); i++)
         {
            A.GetColumnReference(i, Ac);
            Ac.Randomize(seed+i);
         }
      }

      SECTION("Inner product of two primal vectors")
      {
         DenseMatrix tA;
         DenseMatrix At;
         DenseMatrix tAt;

         T.TransformPrimal(u, ut);
         T.TransformPrimal(v, vt);

         T.TransformDualRows(A, At);
         T.TransformDualCols(A, tA);
         T.TransformDual(A, tAt);

         double uAv = A.InnerProduct(v, u);

         REQUIRE(fabs(uAv -  At.InnerProduct(vt, u )) < tol * fabs(uAv));
         REQUIRE(fabs(uAv -  tA.InnerProduct(v , ut)) < tol * fabs(uAv));
         REQUIRE(fabs(uAv - tAt.InnerProduct(vt, ut)) < tol * fabs(uAv));
      }
      SECTION("Inner product of a primal vector and a dual vector")
      {
         DenseMatrix tA;
         DenseMatrix At;
         DenseMatrix tAt;

         T.TransformDual(f, ft);
         T.TransformPrimal(v, vt);

         T.TransformDualRows(A, At);
         T.TransformPrimalCols(A, tA);
         T.TransformPrimalCols(At, tAt);

         double fAv = A.InnerProduct(v, f);

         REQUIRE(fabs(fAv -  At.InnerProduct(vt, f )) < tol * fabs(fAv));
         REQUIRE(fabs(fAv -  tA.InnerProduct(v , ft)) < tol * fabs(fAv));
         REQUIRE(fabs(fAv - tAt.InnerProduct(vt, ft)) < tol * fabs(fAv));
      }
   }
}

} // namespace doftrans
<|endoftext|>


<commit_before>//===- ThreadLocal.cpp - Thread Local Data ----------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the llvm::sys::ThreadLocal class.
//
//===----------------------------------------------------------------------===//

#include "llvm/Config/config.h"
#include "llvm/System/ThreadLocal.h"

//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only TRULY operating system
//===          independent code.
//===----------------------------------------------------------------------===//

#if !defined(ENABLE_THREADS) || ENABLE_THREADS == 0
// Define all methods as no-ops if threading is explicitly disabled
namespace llvm {
using namespace sys;
ThreadLocalImpl::ThreadLocalImpl() { }
ThreadLocalImpl::~ThreadLocalImpl() { }
void ThreadLocalImpl::setInstance(const void* d) { data = const_cast<void*>(d);}
const void* ThreadLocalImpl::getInstance() { return data; }
}
#else

#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_GETSPECIFIC)

#include <cassert>
#include <pthread.h>
#include <stdlib.h>

namespace llvm {
using namespace sys;

ThreadLocalImpl::ThreadLocalImpl() : data(0) {
  pthread_key_t* key = new pthread_key_t;
  int errorcode = pthread_key_create(key, NULL);
  assert(errorcode == 0);
  (void) errorcode;
  data = static_cast<void*>(key);
}

ThreadLocalImpl::~ThreadLocalImpl() {
  pthread_key_t* key = static_cast<pthread_key_t*>(data);
  int errorcode = pthread_key_delete(*key);
  assert(errorcode == 0);
  (void) errorcode;
  delete key;
}

void ThreadLocalImpl::setInstance(const void* d) {
  pthread_key_t* key = static_cast<pthread_key_t*>(data);
  int errorcode = pthread_setspecific(*key, d);
  assert(errorcode == 0);
  (void) errorcode;
}

const void* ThreadLocalImpl::getInstance() {
  pthread_key_t* key = static_cast<pthread_key_t*>(data);
  return pthread_getspecific(*key);
}

}

#elif defined(LLVM_ON_UNIX)
#include "Unix/ThreadLocal.inc"
#elif defined( LLVM_ON_WIN32)
#include "Win32/ThreadLocal.inc"
#else
#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in System/ThreadLocal.cpp
#endif
#endif

<commit_msg>Try again at making this work on OpenBSD.<commit_after>//===- ThreadLocal.cpp - Thread Local Data ----------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the llvm::sys::ThreadLocal class.
//
//===----------------------------------------------------------------------===//

#include "llvm/Config/config.h"
#include "llvm/System/ThreadLocal.h"

//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only TRULY operating system
//===          independent code.
//===----------------------------------------------------------------------===//

#if !defined(ENABLE_THREADS) || ENABLE_THREADS == 0
// Define all methods as no-ops if threading is explicitly disabled
namespace llvm {
using namespace sys;
ThreadLocalImpl::ThreadLocalImpl() { }
ThreadLocalImpl::~ThreadLocalImpl() { }
void ThreadLocalImpl::setInstance(const void* d) { data = const_cast<void*>(d);}
const void* ThreadLocalImpl::getInstance() { return data; }
}
#else

#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_GETSPECIFIC)

#include <cassert>
#include <pthread.h>
#include <stdlib.h>

namespace llvm {
using namespace sys;

ThreadLocalImpl::ThreadLocalImpl() : data(0) {
  pthread_key_t* key = new pthread_key_t;
  int errorcode = pthread_key_create(key, NULL);
  assert(errorcode == 0);
  (void) errorcode;
  data = (void*)key;
}

ThreadLocalImpl::~ThreadLocalImpl() {
  pthread_key_t* key = static_cast<pthread_key_t*>(data);
  int errorcode = pthread_key_delete(*key);
  assert(errorcode == 0);
  (void) errorcode;
  delete key;
}

void ThreadLocalImpl::setInstance(const void* d) {
  pthread_key_t* key = static_cast<pthread_key_t*>(data);
  int errorcode = pthread_setspecific(*key, d);
  assert(errorcode == 0);
  (void) errorcode;
}

const void* ThreadLocalImpl::getInstance() {
  pthread_key_t* key = static_cast<pthread_key_t*>(data);
  return pthread_getspecific(*key);
}

}

#elif defined(LLVM_ON_UNIX)
#include "Unix/ThreadLocal.inc"
#elif defined( LLVM_ON_WIN32)
#include "Win32/ThreadLocal.inc"
#else
#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in System/ThreadLocal.cpp
#endif
#endif

<|endoftext|>


<commit_before>// This file is part of the dune-pymor project:
//   https://github.com/pymor/dune-pymor
// Copyright Holders: Stephan Rave, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifdef HAVE_CMAKE_CONFIG
  #include "cmake_config.h"
#elif defined (HAVE_CONFIG_H)
  #include <config.h>
#endif // HAVE_CMAKE_CONFIG

#include <type_traits>
#include <memory>

#include <dune/stuff/test/test_common.hh>
#include <dune/stuff/la/container/interfaces.hh>
#include <dune/stuff/la/container/dunedynamic.hh>
#include <dune/stuff/la/container/eigen.hh>
#include <dune/stuff/la/container.hh>

#include <dune/pymor/common/exceptions.hh>

using namespace Dune;
using namespace Dune::Pymor;

static const size_t dim = 4;

typedef testing::Types<
                        Dune::Stuff::LA::CommonDenseVector< double >
#if HAVE_EIGEN
                      , Dune::Stuff::LA::EigenDenseVector< double >
#endif
                      > VectorTypes;

typedef testing::Types<
                        Dune::Stuff::LA::CommonDenseMatrix< double >
#if HAVE_EIGEN
                      , Dune::Stuff::LA::EigenRowMajorSparseMatrix< double >
#endif
                      > MatrixTypes;

typedef testing::Types<
                        Dune::Stuff::LA::CommonDenseVector< double >
                      , Dune::Stuff::LA::CommonDenseMatrix< double >
#if HAVE_EIGEN
                      , Dune::Stuff::LA::EigenDenseVector< double >
                      , Dune::Stuff::LA::EigenRowMajorSparseMatrix< double >
#endif
                      > ContainerTypes;

template< class ContainerImp >
struct ContainerTest
  : public ::testing::Test
{
  void check() const
  {
    // static tests
    typedef typename ContainerImp::Traits     Traits;
    // * of the traits
    typedef typename Traits::derived_type     T_derived_type;
    static_assert(std::is_same< ContainerImp, T_derived_type >::value, "derived_type has to be the correct Type!");
    typedef typename Traits::ScalarType       T_ScalarType;
    // * of the container as itself (aka the derived type)
    typedef typename ContainerImp::ScalarType D_ScalarType;
    // * of the container as the interface
    typedef typename Stuff::LA::ContainerInterface< Traits > InterfaceType;
    typedef typename InterfaceType::derived_type      I_derived_type;
    typedef typename InterfaceType::ScalarType        I_ScalarType;
    // dynamic tests
    // * of the container as itself (aka the derived type)
    ContainerImp DUNE_UNUSED(d_empty);
    ContainerImp d_by_size = Stuff::LA::Container< ContainerImp >::create(dim);
    //ContainerImp d_copy_constructor(d_by_size); // <-- this is not allowed!
    //ContainerImp d_copy_assignment = d_by_size; // <-- this is not allowed!
    ContainerImp d_deep_copy = d_by_size.copy();
    d_by_size.scal(D_ScalarType(1));
    d_by_size.axpy(D_ScalarType(1), d_deep_copy);
    if (!d_by_size.has_equal_shape(d_deep_copy)) DUNE_PYMOR_THROW(PymorException, "");
    // * of the container as the interface
    InterfaceType& i_by_size = static_cast< InterfaceType& >(d_by_size);
    ContainerImp i_deep_copy = i_by_size.copy();
    i_by_size.scal(I_ScalarType(1));
    i_by_size.axpy(I_ScalarType(1), i_deep_copy);
  }
}; // struct ContainerTest

TYPED_TEST_CASE(ContainerTest, ContainerTypes);
TYPED_TEST(ContainerTest, LA_CONTAINER) {
  this->check();
}

template< class VectorImp >
struct VectorTest
  : public ::testing::Test
{
  void check() const
  {
    // static tests
    typedef typename VectorImp::Traits      Traits;
    // * of the traits
    typedef typename Traits::derived_type   T_derived_type;
    static_assert(std::is_same< VectorImp,  T_derived_type >::value, "derived_type has to be the correct Type!");
    typedef typename Traits::ScalarType     T_ScalarType;
    // * of the vector as itself (aka the derived type)
    typedef typename VectorImp::ScalarType  D_ScalarType;
    // * of the vector as the interface
    typedef typename Stuff::LA::VectorInterface< Traits >  InterfaceType;
    typedef typename InterfaceType::derived_type    I_derived_type;
    typedef typename InterfaceType::ScalarType      I_ScalarType;
    // dynamic tests
    // * of the vector as itself (aka the derived type)
    VectorImp d_by_size(dim);
    VectorImp d_by_size_and_value(dim, D_ScalarType(1));
    DUNE_STUFF_SSIZE_T DUNE_UNUSED(d_dim) = d_by_size.dim();
    bool d_almost_equal = d_by_size.almost_equal(d_by_size);
    if (!d_almost_equal) DUNE_PYMOR_THROW(PymorException, "");
    d_by_size_and_value.scal(D_ScalarType(0));
    if (!d_by_size_and_value.almost_equal(d_by_size)) DUNE_PYMOR_THROW(PymorException, "");
    D_ScalarType d_dot = d_by_size.dot(d_by_size_and_value);
    if (!Dune::FloatCmp::eq(d_dot, D_ScalarType(0))) DUNE_PYMOR_THROW(PymorException, d_dot);
    D_ScalarType d_l1_norm = d_by_size.l1_norm();
    if (!Dune::FloatCmp::eq(d_l1_norm, D_ScalarType(0))) DUNE_PYMOR_THROW(PymorException, d_l1_norm);
    D_ScalarType d_l2_norm = d_by_size.l2_norm();
    if (!Dune::FloatCmp::eq(d_l2_norm, D_ScalarType(0))) DUNE_PYMOR_THROW(PymorException, d_l2_norm);
    D_ScalarType d_sup_norm = d_by_size.sup_norm();
    if (!Dune::FloatCmp::eq(d_sup_norm ,D_ScalarType(0))) DUNE_PYMOR_THROW(PymorException, d_sup_norm);
    VectorImp d_ones(dim, D_ScalarType(1));
    std::pair< size_t, D_ScalarType > d_amax = d_ones.amax();
    if (d_amax.first != 0 || !Dune::FloatCmp::eq(d_amax.second, D_ScalarType(1))) DUNE_PYMOR_THROW(PymorException, "");
    d_ones.add(d_by_size, d_by_size_and_value);
    if (!d_by_size_and_value.almost_equal(d_ones)) DUNE_PYMOR_THROW(PymorException, "");
    VectorImp d_added = d_ones.add(d_by_size);
    if (!d_added.almost_equal(d_by_size_and_value)) DUNE_PYMOR_THROW(PymorException, "");
    d_added.iadd(d_by_size);
    if (!d_added.almost_equal(d_ones)) DUNE_PYMOR_THROW(PymorException, "");
    d_ones.sub(d_by_size, d_by_size_and_value);
    if (!d_by_size_and_value.almost_equal(d_ones)) DUNE_PYMOR_THROW(PymorException, "");
    VectorImp d_subtracted = d_ones.sub(d_by_size);
    if (!d_subtracted.almost_equal(d_by_size_and_value)) DUNE_PYMOR_THROW(PymorException, "");
    d_subtracted.isub(d_by_size);
    if (!d_subtracted.almost_equal(d_ones)) DUNE_PYMOR_THROW(PymorException, "");
    // * of the vector as the interface
    VectorImp d_by_size_2(dim);
    VectorImp d_by_size_and_value_2(dim, D_ScalarType(1));
    InterfaceType& i_by_size = static_cast< InterfaceType& >(d_by_size_2);
    InterfaceType& i_by_size_and_value = static_cast< InterfaceType& >(d_by_size_and_value_2);
    DUNE_STUFF_SSIZE_T DUNE_UNUSED(i_dim) = i_by_size.dim();
    bool i_almost_equal = i_by_size.almost_equal(d_by_size_2);
    if (!i_almost_equal) DUNE_PYMOR_THROW(PymorException, "");
    i_by_size_and_value.scal(I_ScalarType(0));
    if (!i_by_size_and_value.almost_equal(d_by_size_2)) DUNE_PYMOR_THROW(PymorException, "");
    I_ScalarType i_dot = i_by_size.dot(d_by_size_and_value_2);
    if (!Dune::FloatCmp::eq(i_dot, I_ScalarType(0))) DUNE_PYMOR_THROW(PymorException, i_dot);
    I_ScalarType i_l1_norm = i_by_size.l1_norm();
    if (!Dune::FloatCmp::eq(i_l1_norm, I_ScalarType(0))) DUNE_PYMOR_THROW(PymorException, i_l1_norm);
    I_ScalarType i_l2_norm = i_by_size.l2_norm();
    if (!Dune::FloatCmp::eq(i_l2_norm, I_ScalarType(0))) DUNE_PYMOR_THROW(PymorException, i_l2_norm);
    I_ScalarType i_sup_norm = i_by_size.sup_norm();
    if (!Dune::FloatCmp::eq(i_sup_norm ,I_ScalarType(0))) DUNE_PYMOR_THROW(PymorException, i_sup_norm);
    VectorImp i_ones(dim, I_ScalarType(1));
    std::pair< size_t, I_ScalarType > i_amax = i_ones.amax();
    if (i_amax.first != 0 || !Dune::FloatCmp::eq(i_amax.second, I_ScalarType(1))) DUNE_PYMOR_THROW(PymorException, "");
    i_ones.add(d_by_size_2, d_by_size_and_value_2);
    if (!i_by_size_and_value.almost_equal(i_ones)) DUNE_PYMOR_THROW(PymorException, "");
    VectorImp i_added = i_ones.add(d_by_size_2);
    if (!i_added.almost_equal(d_by_size_and_value_2)) DUNE_PYMOR_THROW(PymorException, "");
    i_added.iadd(d_by_size_2);
    if (!i_added.almost_equal(i_ones)) DUNE_PYMOR_THROW(PymorException, "");
    i_ones.sub(d_by_size_2, d_by_size_and_value_2);
    if (!i_by_size_and_value.almost_equal(i_ones)) DUNE_PYMOR_THROW(PymorException, "");
    VectorImp i_subtracted = i_ones.sub(d_by_size_2);
    if (!i_subtracted.almost_equal(d_by_size_and_value_2)) DUNE_PYMOR_THROW(PymorException, "");
    i_subtracted.isub(d_by_size_2);
    if (!i_subtracted.almost_equal(i_ones)) DUNE_PYMOR_THROW(PymorException, "");
  }
}; // struct VectorTest

TYPED_TEST_CASE(VectorTest, VectorTypes);
TYPED_TEST(VectorTest, LA_CONTAINER) {
  this->check();
}

int main(int argc, char** argv)
{
  try {
    test_init(argc, argv);
    return RUN_ALL_TESTS();
  } catch (Dune::PymorException& e) {
    std::cerr << Dune::Stuff::Common::colorStringRed("dune-pymor reported: ") << e << std::endl;
  } catch (Dune::Exception& e) {
    std::cerr << Dune::Stuff::Common::colorStringRed("Dune reported error: ") << e << std::endl;
  } catch (...) {
    std::cerr << Dune::Stuff::Common::colorStringRed("Unknown exception thrown!") << std::endl;
  }
}
<commit_msg>[test.la_container] update<commit_after>// This file is part of the dune-pymor project:
//   https://github.com/pymor/dune-pymor
// Copyright Holders: Stephan Rave, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#include <dune/stuff/test/test_common.hh>

#include <type_traits>
#include <memory>

#include <dune/stuff/la/container/interfaces.hh>
#include <dune/stuff/la/container/common.hh>
#include <dune/stuff/la/container/eigen.hh>
#include <dune/stuff/la/container.hh>

#include <dune/pymor/common/exceptions.hh>

using namespace Dune;
using namespace Dune::Pymor;

static const size_t dim = 4;

typedef testing::Types<
                        Dune::Stuff::LA::CommonDenseVector< double >
#if HAVE_EIGEN
                      , Dune::Stuff::LA::EigenDenseVector< double >
#endif
                      > VectorTypes;

typedef testing::Types<
                        Dune::Stuff::LA::CommonDenseMatrix< double >
#if HAVE_EIGEN
                      , Dune::Stuff::LA::EigenRowMajorSparseMatrix< double >
#endif
                      > MatrixTypes;

typedef testing::Types<
                        Dune::Stuff::LA::CommonDenseVector< double >
                      , Dune::Stuff::LA::CommonDenseMatrix< double >
#if HAVE_EIGEN
                      , Dune::Stuff::LA::EigenDenseVector< double >
                      , Dune::Stuff::LA::EigenRowMajorSparseMatrix< double >
#endif
                      > ContainerTypes;

template< class ContainerImp >
struct ContainerTest
  : public ::testing::Test
{
  void check() const
  {
    // static tests
    typedef typename ContainerImp::Traits     Traits;
    // * of the traits
    typedef typename Traits::derived_type     T_derived_type;
    static_assert(std::is_same< ContainerImp, T_derived_type >::value, "derived_type has to be the correct Type!");
    typedef typename Traits::ScalarType       T_ScalarType;
    // * of the container as itself (aka the derived type)
    typedef typename ContainerImp::ScalarType D_ScalarType;
    // * of the container as the interface
    typedef typename Stuff::LA::ContainerInterface< Traits > InterfaceType;
    typedef typename InterfaceType::derived_type      I_derived_type;
    typedef typename InterfaceType::ScalarType        I_ScalarType;
    // dynamic tests
    // * of the container as itself (aka the derived type)
    ContainerImp DUNE_UNUSED(d_empty);
    ContainerImp d_by_size = Stuff::LA::Container< ContainerImp >::create(dim);
    //ContainerImp d_copy_constructor(d_by_size); // <-- this is not allowed!
    //ContainerImp d_copy_assignment = d_by_size; // <-- this is not allowed!
    ContainerImp d_deep_copy = d_by_size.copy();
    d_by_size.scal(D_ScalarType(1));
    d_by_size.axpy(D_ScalarType(1), d_deep_copy);
    if (!d_by_size.has_equal_shape(d_deep_copy)) DUNE_PYMOR_THROW(PymorException, "");
    // * of the container as the interface
    InterfaceType& i_by_size = static_cast< InterfaceType& >(d_by_size);
    ContainerImp i_deep_copy = i_by_size.copy();
    i_by_size.scal(I_ScalarType(1));
    i_by_size.axpy(I_ScalarType(1), i_deep_copy);
  }
}; // struct ContainerTest

TYPED_TEST_CASE(ContainerTest, ContainerTypes);
TYPED_TEST(ContainerTest, LA_CONTAINER) {
  this->check();
}

template< class VectorImp >
struct VectorTest
  : public ::testing::Test
{
  void check() const
  {
    // static tests
    typedef typename VectorImp::Traits      Traits;
    // * of the traits
    typedef typename Traits::derived_type   T_derived_type;
    static_assert(std::is_same< VectorImp,  T_derived_type >::value, "derived_type has to be the correct Type!");
    typedef typename Traits::ScalarType     T_ScalarType;
    // * of the vector as itself (aka the derived type)
    typedef typename VectorImp::ScalarType  D_ScalarType;
    // * of the vector as the interface
    typedef typename Stuff::LA::VectorInterface< Traits >  InterfaceType;
    typedef typename InterfaceType::derived_type    I_derived_type;
    typedef typename InterfaceType::ScalarType      I_ScalarType;
    // dynamic tests
    // * of the vector as itself (aka the derived type)
    VectorImp d_by_size(dim);
    VectorImp d_by_size_and_value(dim, D_ScalarType(1));
    DUNE_STUFF_SSIZE_T DUNE_UNUSED(d_dim) = d_by_size.dim();
    bool d_almost_equal = d_by_size.almost_equal(d_by_size);
    if (!d_almost_equal) DUNE_PYMOR_THROW(PymorException, "");
    d_by_size_and_value.scal(D_ScalarType(0));
    if (!d_by_size_and_value.almost_equal(d_by_size)) DUNE_PYMOR_THROW(PymorException, "");
    D_ScalarType d_dot = d_by_size.dot(d_by_size_and_value);
    if (!Dune::FloatCmp::eq(d_dot, D_ScalarType(0))) DUNE_PYMOR_THROW(PymorException, d_dot);
    D_ScalarType d_l1_norm = d_by_size.l1_norm();
    if (!Dune::FloatCmp::eq(d_l1_norm, D_ScalarType(0))) DUNE_PYMOR_THROW(PymorException, d_l1_norm);
    D_ScalarType d_l2_norm = d_by_size.l2_norm();
    if (!Dune::FloatCmp::eq(d_l2_norm, D_ScalarType(0))) DUNE_PYMOR_THROW(PymorException, d_l2_norm);
    D_ScalarType d_sup_norm = d_by_size.sup_norm();
    if (!Dune::FloatCmp::eq(d_sup_norm ,D_ScalarType(0))) DUNE_PYMOR_THROW(PymorException, d_sup_norm);
    VectorImp d_ones(dim, D_ScalarType(1));
    std::pair< size_t, D_ScalarType > d_amax = d_ones.amax();
    if (d_amax.first != 0 || !Dune::FloatCmp::eq(d_amax.second, D_ScalarType(1))) DUNE_PYMOR_THROW(PymorException, "");
    d_ones.add(d_by_size, d_by_size_and_value);
    if (!d_by_size_and_value.almost_equal(d_ones)) DUNE_PYMOR_THROW(PymorException, "");
    VectorImp d_added = d_ones.add(d_by_size);
    if (!d_added.almost_equal(d_by_size_and_value)) DUNE_PYMOR_THROW(PymorException, "");
    d_added.iadd(d_by_size);
    if (!d_added.almost_equal(d_ones)) DUNE_PYMOR_THROW(PymorException, "");
    d_ones.sub(d_by_size, d_by_size_and_value);
    if (!d_by_size_and_value.almost_equal(d_ones)) DUNE_PYMOR_THROW(PymorException, "");
    VectorImp d_subtracted = d_ones.sub(d_by_size);
    if (!d_subtracted.almost_equal(d_by_size_and_value)) DUNE_PYMOR_THROW(PymorException, "");
    d_subtracted.isub(d_by_size);
    if (!d_subtracted.almost_equal(d_ones)) DUNE_PYMOR_THROW(PymorException, "");
    // * of the vector as the interface
    VectorImp d_by_size_2(dim);
    VectorImp d_by_size_and_value_2(dim, D_ScalarType(1));
    InterfaceType& i_by_size = static_cast< InterfaceType& >(d_by_size_2);
    InterfaceType& i_by_size_and_value = static_cast< InterfaceType& >(d_by_size_and_value_2);
    DUNE_STUFF_SSIZE_T DUNE_UNUSED(i_dim) = i_by_size.dim();
    bool i_almost_equal = i_by_size.almost_equal(d_by_size_2);
    if (!i_almost_equal) DUNE_PYMOR_THROW(PymorException, "");
    i_by_size_and_value.scal(I_ScalarType(0));
    if (!i_by_size_and_value.almost_equal(d_by_size_2)) DUNE_PYMOR_THROW(PymorException, "");
    I_ScalarType i_dot = i_by_size.dot(d_by_size_and_value_2);
    if (!Dune::FloatCmp::eq(i_dot, I_ScalarType(0))) DUNE_PYMOR_THROW(PymorException, i_dot);
    I_ScalarType i_l1_norm = i_by_size.l1_norm();
    if (!Dune::FloatCmp::eq(i_l1_norm, I_ScalarType(0))) DUNE_PYMOR_THROW(PymorException, i_l1_norm);
    I_ScalarType i_l2_norm = i_by_size.l2_norm();
    if (!Dune::FloatCmp::eq(i_l2_norm, I_ScalarType(0))) DUNE_PYMOR_THROW(PymorException, i_l2_norm);
    I_ScalarType i_sup_norm = i_by_size.sup_norm();
    if (!Dune::FloatCmp::eq(i_sup_norm ,I_ScalarType(0))) DUNE_PYMOR_THROW(PymorException, i_sup_norm);
    VectorImp i_ones(dim, I_ScalarType(1));
    std::pair< size_t, I_ScalarType > i_amax = i_ones.amax();
    if (i_amax.first != 0 || !Dune::FloatCmp::eq(i_amax.second, I_ScalarType(1))) DUNE_PYMOR_THROW(PymorException, "");
    i_ones.add(d_by_size_2, d_by_size_and_value_2);
    if (!i_by_size_and_value.almost_equal(i_ones)) DUNE_PYMOR_THROW(PymorException, "");
    VectorImp i_added = i_ones.add(d_by_size_2);
    if (!i_added.almost_equal(d_by_size_and_value_2)) DUNE_PYMOR_THROW(PymorException, "");
    i_added.iadd(d_by_size_2);
    if (!i_added.almost_equal(i_ones)) DUNE_PYMOR_THROW(PymorException, "");
    i_ones.sub(d_by_size_2, d_by_size_and_value_2);
    if (!i_by_size_and_value.almost_equal(i_ones)) DUNE_PYMOR_THROW(PymorException, "");
    VectorImp i_subtracted = i_ones.sub(d_by_size_2);
    if (!i_subtracted.almost_equal(d_by_size_and_value_2)) DUNE_PYMOR_THROW(PymorException, "");
    i_subtracted.isub(d_by_size_2);
    if (!i_subtracted.almost_equal(i_ones)) DUNE_PYMOR_THROW(PymorException, "");
  }
}; // struct VectorTest

TYPED_TEST_CASE(VectorTest, VectorTypes);
TYPED_TEST(VectorTest, LA_CONTAINER) {
  this->check();
}

int main(int argc, char** argv)
{
  try {
    test_init(argc, argv);
    return RUN_ALL_TESTS();
  } catch (Dune::PymorException& e) {
    std::cerr << Dune::Stuff::Common::colorStringRed("dune-pymor reported: ") << e << std::endl;
  } catch (Dune::Exception& e) {
    std::cerr << Dune::Stuff::Common::colorStringRed("Dune reported error: ") << e << std::endl;
  } catch (...) {
    std::cerr << Dune::Stuff::Common::colorStringRed("Unknown exception thrown!") << std::endl;
  }
}
<|endoftext|>


<commit_before>#include <iostream>

using namespace std;<commit_msg>add hello world<commit_after>#include <iostream>

using namespace std;

int main(){

    cout<<"hello world!"<<endl;
}<|endoftext|>


<commit_before>/*
    BelaCsound.cpp:

    Copyright (C) 2017 V Lazzarini

    This file is part of Csound.

    The Csound Library is free software; you can redistribute it
    and/or modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    Csound is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with Csound; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA
*/
#include <Bela.h>
#include <Midi.h>
#include <csound/csound.hpp>
#include <vector>
#include <sstream>

#define ANCHNS 8

static int OpenMidiInDevice(CSOUND *csound, void **userData, const char *dev);
static int CloseMidiInDevice(CSOUND *csound, void *userData);
static int ReadMidiData(CSOUND *csound, void *userData, unsigned char *mbuf,
			int nbytes);

struct CsChan {
  std::vector<MYFLT> data;
  std::stringstream name;
};

struct CsData {
  Csound *csound;
  int blocksize;
  int res;
  int count;
  CsChan channel[ANCHNS];
};

static CsData gCsData;

bool setup(BelaContext *context, void *Data)
{
  Csound *csound;
  const char *csdfile = "my.csd"; /* CSD name */
  const char *midiDev = "-Mhw:1,0,0"; /* MIDI device */
  const char *args[] = { "csound", csdfile, "-iadc", "-odac", "-+rtaudio=null",
			 "--realtime", "--daemon", midiDev };
  int numArgs = (int) (sizeof(args)/sizeof(char *));

  if(context->audioInChannels != context->audioOutChannels) {
    printf("Error: number of audio inputs != number of audio outputs.\n");
    return false;
  }

  /* setup Csound */
  csound = new Csound();
  gCsData.csound = csound;
  csound->SetHostImplementedAudioIO(1,0);
  csound->SetHostImplementedMIDIIO(1);
  csound->SetExternalMidiInOpenCallback(OpenMidiInDevice);
  csound->SetExternalMidiReadCallback(ReadMidiData);
  csound->SetExternalMidiInCloseCallback(CloseMidiInDevice);
  if((gCsData.res = csound->Compile(numArgs, args)) != 0) {
    printf("Error: Csound could not compile CSD file.\n");
    return false;
  }
  gCsData.blocksize = csound->GetKsmps()*csound->GetNchnls();
  gCsData.count = 0;

  /* set up the channels */
  for(int i; i < ANCHNS; i++) {
    gCsData.channel[i].data.resize(csound->GetKsmps());
    gCsData.channel[i].name << "analogue" << i+1;
  }

  return true;
}

void render(BelaContext *context, void *Data)
{
  if(gCsData.res == 0) {
    int n,i,k,count, frmcount,blocksize,res;
    Csound *csound = gCsData.csound;
    MYFLT scal = csound->Get0dBFS();
    MYFLT* audioIn = csound->GetSpin();
    MYFLT* audioOut = csound->GetSpout();
    int nchnls = csound->GetNchnls();
    int chns = nchnls < context->audioOutChannels ?
      nchnls : context->audioOutChannels;
    int an_chns = context->analogInChannels > ANCHNS ?
      ANCHNS : context->analogInChannels;
    CsChan *channel = &(gCsData.channel[0]);
    float frm = 0.f, incr = ((float) context->analogFrames)/context->audioFrames;
    count = gCsData.count;
    blocksize = gCsData.blocksize;

    /* processing loop */
    for(n = 0; n < context->audioFrames; n++, frm+=incr, count+=nchnls){
      if(count == blocksize) {
	/* set the channels */
	for(i = 0; i < an_chns; i++) {
          csound->SetChannel(channel[i].name.str().c_str(),
			     &(channel[i].data[0]));
	}
	/* run csound */
	if((res = csound->PerformKsmps()) == 0) count = 0;
	else break;
      }
      /* read/write audio data */
      for(i = 0; i < chns; i++){
	audioIn[count+i] = audioRead(context,n,i);
	audioWrite(context,n,i,audioOut[count+i]/scal);
      }
      /* read analogue data
         analogue frame pos frm gets incremented according to the
         ratio analogFrames/audioFrames.
      */
      frmcount = count/nchnls;
      for(i = 0; i < an_chns; i++) {
	k = (int) frm;
        channel[i].data[frmcount] = analogRead(context,k,i);
      }
    }
    gCsData.res = res;
    gCsData.count = count;
  }
}

void cleanup(BelaContext *context, void *Data)
{
  delete gCsData.csound;
}

/** MIDI Input functions
 */
int OpenMidiInDevice(CSOUND *csound, void **userData, const char *dev) {
  Midi *midi = new Midi;
  midi->readFrom(dev);
  midi->enableParser(false);
  *userData = (void *) midi;
}

int CloseMidiInDevice(CSOUND *csound, void *userData) {
  delete (Midi *) userData;
}

int ReadMidiData(CSOUND *csound, void *userData,
		 unsigned char *mbuf, int nbytes) {
  int n = 0, byte;
  Midi midi = (Midi *) userData;

  while((byte = midi->getInput()) >= 0) {
    *mbuf++ = (unsigned char) byte;
    if(++n == nbytes) break;
  }

  return n;
}
<commit_msg>protecting midi open<commit_after>/*
    BelaCsound.cpp:

    Copyright (C) 2017 V Lazzarini

    This file is part of Csound.

    The Csound Library is free software; you can redistribute it
    and/or modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    Csound is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with Csound; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA
*/
#include <Bela.h>
#include <Midi.h>
#include <csound/csound.hpp>
#include <vector>
#include <sstream>

#define ANCHNS 8

static int OpenMidiInDevice(CSOUND *csound, void **userData, const char *dev);
static int CloseMidiInDevice(CSOUND *csound, void *userData);
static int ReadMidiData(CSOUND *csound, void *userData, unsigned char *mbuf,
			int nbytes);

struct CsChan {
  std::vector<MYFLT> data;
  std::stringstream name;
};

struct CsData {
  Csound *csound;
  int blocksize;
  int res;
  int count;
  CsChan channel[ANCHNS];
};

static CsData gCsData;

bool setup(BelaContext *context, void *Data)
{
  Csound *csound;
  const char *csdfile = "my.csd"; /* CSD name */
  const char *midiDev = "-Mhw:1,0,0"; /* MIDI device */
  const char *args[] = { "csound", csdfile, "-iadc", "-odac", "-+rtaudio=null",
			 "--realtime", "--daemon", midiDev };
  int numArgs = (int) (sizeof(args)/sizeof(char *));

  if(context->audioInChannels != context->audioOutChannels) {
    printf("Error: number of audio inputs != number of audio outputs.\n");
    return false;
  }

  /* setup Csound */
  csound = new Csound();
  gCsData.csound = csound;
  csound->SetHostImplementedAudioIO(1,0);
  csound->SetHostImplementedMIDIIO(1);
  csound->SetExternalMidiInOpenCallback(OpenMidiInDevice);
  csound->SetExternalMidiReadCallback(ReadMidiData);
  csound->SetExternalMidiInCloseCallback(CloseMidiInDevice);
  if((gCsData.res = csound->Compile(numArgs, args)) != 0) {
    printf("Error: Csound could not compile CSD file.\n");
    return false;
  }
  gCsData.blocksize = csound->GetKsmps()*csound->GetNchnls();
  gCsData.count = 0;

  /* set up the channels */
  for(int i; i < ANCHNS; i++) {
    gCsData.channel[i].data.resize(csound->GetKsmps());
    gCsData.channel[i].name << "analogue" << i+1;
  }

  return true;
}

void render(BelaContext *context, void *Data)
{
  if(gCsData.res == 0) {
    int n,i,k,count, frmcount,blocksize,res;
    Csound *csound = gCsData.csound;
    MYFLT scal = csound->Get0dBFS();
    MYFLT* audioIn = csound->GetSpin();
    MYFLT* audioOut = csound->GetSpout();
    int nchnls = csound->GetNchnls();
    int chns = nchnls < context->audioOutChannels ?
      nchnls : context->audioOutChannels;
    int an_chns = context->analogInChannels > ANCHNS ?
      ANCHNS : context->analogInChannels;
    CsChan *channel = &(gCsData.channel[0]);
    float frm = 0.f, incr = ((float) context->analogFrames)/context->audioFrames;
    count = gCsData.count;
    blocksize = gCsData.blocksize;

    /* processing loop */
    for(n = 0; n < context->audioFrames; n++, frm+=incr, count+=nchnls){
      if(count == blocksize) {
	/* set the channels */
	for(i = 0; i < an_chns; i++) {
          csound->SetChannel(channel[i].name.str().c_str(),
			     &(channel[i].data[0]));
	}
	/* run csound */
	if((res = csound->PerformKsmps()) == 0) count = 0;
	else break;
      }
      /* read/write audio data */
      for(i = 0; i < chns; i++){
	audioIn[count+i] = audioRead(context,n,i);
	audioWrite(context,n,i,audioOut[count+i]/scal);
      }
      /* read analogue data
         analogue frame pos frm gets incremented according to the
         ratio analogFrames/audioFrames.
      */
      frmcount = count/nchnls;
      for(i = 0; i < an_chns; i++) {
	k = (int) frm;
        channel[i].data[frmcount] = analogRead(context,k,i);
      }
    }
    gCsData.res = res;
    gCsData.count = count;
  }
}

void cleanup(BelaContext *context, void *Data)
{
  delete gCsData.csound;
}

/** MIDI Input functions
 */
int OpenMidiInDevice(CSOUND *csound, void **userData, const char *dev) {
  Midi *midi = new Midi;
  if(midi->readFrom(dev) == 1) {
    midi->enableParser(false);
    *userData = (void *) midi;
    return 0;
  }
  csound->Warning(csound, "Could not open Midi device %s", dev);
  delete Midi;
  return -1;
}

int CloseMidiInDevice(CSOUND *csound, void *userData) {
  if(userData) delete (Midi *) userData;
}

int ReadMidiData(CSOUND *csound, void *userData,
		 unsigned char *mbuf, int nbytes) {
  int n = 0, byte;
  if(userData) {
  Midi *midi = (Midi *) userData;

  while((byte = midi->getInput()) >= 0) {
    *mbuf++ = (unsigned char) byte;
    if(++n == nbytes) break;
  }
  return n;
  }
  return 0;
}
<|endoftext|>