<commit_before>/* vim: set sw=4 sts=4 et foldmethod=syntax : */

#include <max_clique/dbmcsa_max_clique.hh>
#include <max_clique/colourise.hh>
#include <max_clique/print_incumbent.hh>
#include <graph/degree_sort.hh>
#include <graph/min_width_sort.hh>
#include <threads/atomic_incumbent.hh>

#include <algorithm>
#include <thread>
#include <condition_variable>
#include <mutex>

using namespace parasols;

namespace
{
    template <unsigned size_>
    struct Job
    {
        std::mutex mutex;
        std::array<unsigned, size_ * bits_per_word> p_order;
        std::array<unsigned, size_ * bits_per_word> colours;
        FixedBitSet<size_> c;
        FixedBitSet<size_> p;
    };

    template <unsigned size_>
    auto found_possible_new_best(
            const FixedBitGraph<size_> & graph,
            const std::vector<int> & o,
            const FixedBitSet<size_> & c,
            int c_popcount,
            const MaxCliqueParams & params,
            MaxCliqueResult & result,
            AtomicIncumbent & best_anywhere) -> void
    {
        if (best_anywhere.update(c_popcount)) {
            result.size = c_popcount;
            result.members.clear();
            for (int i = 0 ; i < graph.size() ; ++i)
                if (c.test(i))
                    result.members.insert(o[i]);
            print_incumbent(params, result.size);
        }
    }

    auto bound(unsigned c_popcount, unsigned cn, const MaxCliqueParams & params, AtomicIncumbent & best_anywhere) -> bool
    {
        unsigned best_anywhere_value = best_anywhere.get();
        return (c_popcount + cn <= best_anywhere_value || best_anywhere_value >= params.stop_after_finding);
    }

    template <unsigned size_>
    auto expand_unstealable(
            const FixedBitGraph<size_> & graph,
            const std::vector<int> & o,                      // vertex ordering
            const std::array<unsigned, size_ * bits_per_word> & p_order,
            const std::array<unsigned, size_ * bits_per_word> & colours,
            FixedBitSet<size_> & c,                          // current candidate clique
            FixedBitSet<size_> & p,                          // potential additions
            MaxCliqueResult & result,
            AtomicIncumbent & best_anywhere,
            const MaxCliqueParams & params
            ) -> void
    {
        auto c_popcount = c.popcount();
        int n = p.popcount() - 1;

        // bound, timeout or early exit?
        if (bound(c_popcount, colours[n], params, best_anywhere) || params.abort.load())
            return;

        auto v = p_order[n];

        // consider taking v
        c.set(v);
        ++c_popcount;

        // filter p to contain vertices adjacent to v
        FixedBitSet<size_> new_p = p;
        graph.intersect_with_row(v, new_p);

        if (new_p.empty()) {
            found_possible_new_best(graph, o, c, c_popcount, params, result, best_anywhere);
        }
        else {
            // get our coloured vertices
            ++result.nodes;
            std::array<unsigned, size_ * bits_per_word> new_p_order, new_colours;
            colourise<size_>(graph, new_p, new_p_order, new_colours);
            expand_unstealable<size_>(graph, o, new_p_order, new_colours, c, new_p, result, best_anywhere, params);
        }

        // now consider not taking v
        c.unset(v);
        p.unset(v);
        if (n > 0) {
            expand_unstealable<size_>(graph, o, p_order, colours, c, p, result, best_anywhere, params);
        }
    }

    template <unsigned size_>
    auto expand(
            const FixedBitGraph<size_> & graph,
            const std::vector<int> & o,
            Job<size_> * job,
            std::unique_lock<std::mutex> & job_guard,
            Job<size_> * child_job,
            std::mutex & stealing_mutex,
            std::condition_variable & stealing_cv,
            std::list<Job<size_> *> & steal_queue,
            MaxCliqueResult & result,
            AtomicIncumbent & best_anywhere,
            const MaxCliqueParams & params
            ) -> bool
    {
        auto job_c_popcount = job->c.popcount();
        int n = job->p.popcount() - 1;

        // bound, timeout or early exit?
        if (-1 == n || bound(job_c_popcount, job->colours[n], params, best_anywhere) || params.abort.load())
            return false;

        auto v = job->p_order[n];

        auto c = job->c;
        auto p = job->p;

        // prepare next step in the job
        job->c.unset(v);
        job->p.unset(v);
        job_guard.unlock();

        // consider taking v
        c.set(v);

        // filter p to contain vertices adjacent to v
        FixedBitSet<size_> new_p = p;
        graph.intersect_with_row(v, new_p);

        if (new_p.empty()) {
            found_possible_new_best(graph, o, c, c.popcount(), params, result, best_anywhere);
        }
        else {
            // get our coloured vertices
            ++result.nodes;

            if (child_job) {
                child_job->c = c;
                child_job->p = new_p;
                colourise<size_>(graph, child_job->p, child_job->p_order, child_job->colours);

                {
                    std::unique_lock<std::mutex> guard(stealing_mutex);
                    steal_queue.push_back(child_job);
                    stealing_cv.notify_all();
                }

                while (true) {
                    std::unique_lock<std::mutex> child_job_guard(child_job->mutex);
                    if (! expand<size_>(graph, o, child_job, child_job_guard, nullptr,
                                stealing_mutex, stealing_cv, steal_queue, result, best_anywhere, params))
                        break;
                }

                {
                    std::unique_lock<std::mutex> guard(stealing_mutex);
                    steal_queue.remove(child_job);
                }
            }
            else {
                std::array<unsigned, size_ * bits_per_word> new_p_order, new_colours;
                colourise<size_>(graph, new_p, new_p_order, new_colours);
                expand_unstealable<size_>(graph, o, new_p_order, new_colours, c, new_p, result, best_anywhere, params);
            }
        }

        return true;
    }

    template <MaxCliqueOrder order_, unsigned size_>
    auto dbmcsa(const Graph & graph, const MaxCliqueParams & params) -> MaxCliqueResult
    {
        MaxCliqueResult result;
        std::mutex result_mutex;
        result.size = params.initial_bound;

        AtomicIncumbent best_anywhere; // global incumbent
        best_anywhere.update(params.initial_bound);

        std::vector<int> o(graph.size()); // vertex ordering

        // populate our order with every vertex initially
        std::iota(o.begin(), o.end(), 0);

        switch (order_) {
            case MaxCliqueOrder::Degree:
                degree_sort(graph, o, false);
                break;
            case MaxCliqueOrder::MinWidth:
                min_width_sort(graph, o, false);
                break;
            case MaxCliqueOrder::ExDegree:
                exdegree_sort(graph, o, false);
                break;
            case MaxCliqueOrder::DynExDegree:
                dynexdegree_sort(graph, o, false);
                break;
        }

        // re-encode graph as a bit graph
        FixedBitGraph<size_> bit_graph;
        bit_graph.resize(graph.size());

        for (int i = 0 ; i < graph.size() ; ++i)
            for (int j = 0 ; j < graph.size() ; ++j)
                if (graph.adjacent(o[i], o[j]))
                    bit_graph.add_edge(i, j);

        // initial ordering
        ++result.nodes;

        Job<size_> top_job;

        // first job
        top_job.c.resize(graph.size());
        top_job.p.resize(graph.size());
        top_job.p.set_all();
        colourise<size_>(bit_graph, top_job.p, top_job.p_order, top_job.colours);

        std::mutex stealing_mutex;
        std::condition_variable stealing_cv;
        bool finished = false;
        int number_busy = params.n_threads;
        std::list<Job<size_> *> steal_queue;

        std::list<std::thread> threads; // workers
        for (unsigned i = 0 ; i < params.n_threads ; ++i) {
            threads.push_back(std::thread([&, i] {

                auto start_time = std::chrono::steady_clock::now(); // local start time
                auto last_useful_time = start_time; // gets updated
                MaxCliqueResult tr; // local result

                Job<size_> this_thread_job;

                while (true) {
                    std::unique_lock<std::mutex> guard(top_job.mutex);
                    if (! expand<size_>(bit_graph, o,
                            &top_job, guard, &this_thread_job,
                            stealing_mutex, stealing_cv, steal_queue,
                            tr, best_anywhere, params))
                        break;
                }

                last_useful_time = std::chrono::steady_clock::now();

                while (true) {
                    std::unique_lock<std::mutex> guard(stealing_mutex);
                    if (finished)
                        break;

                    if (0 == --number_busy) {
                        finished = true;
                        stealing_cv.notify_all();
                    } else {
                        bool found_something = false;
                        for (auto s = steal_queue.begin() ; s != steal_queue.end() ; ++s) {
                            std::unique_lock<std::mutex> steal_guard((*s)->mutex);
                            if (! (*s)->p.empty()) {
                                found_something = true;
                                ++number_busy;
                                bool resplit = ((*s)->c.popcount() <= 1);
                                guard.unlock();
                                expand<size_>(bit_graph, o, *s, steal_guard, resplit ? &this_thread_job : nullptr,
                                        stealing_mutex, stealing_cv, steal_queue, tr, best_anywhere, params);
                                last_useful_time = std::chrono::steady_clock::now();
                                break;
                            }
                        }

                        if (! found_something)
                            stealing_cv.wait(guard);
                    }
                }

                auto overall_time = std::chrono::duration_cast<std::chrono::milliseconds>(last_useful_time - start_time);

                // merge results
                {
                    std::unique_lock<std::mutex> guard(result_mutex);
                    result.merge(tr);
                    result.times.push_back(overall_time);
                }
            }));
        }

        for (auto & t : threads)
            t.join();

        return result;
    }
}

template <MaxCliqueOrder order_>
auto parasols::dbmcsa_max_clique(const Graph & graph, const MaxCliqueParams & params) -> MaxCliqueResult
{
    /* This is pretty horrible: in order to avoid dynamic allocation, select
     * the appropriate specialisation for our graph's size. */
    static_assert(max_graph_words == 1024, "Need to update here if max_graph_size is changed.");
    if (graph.size() < bits_per_word)
        return dbmcsa<order_, 1>(graph, params);
    else if (graph.size() < 2 * bits_per_word)
        return dbmcsa<order_, 2>(graph, params);
    else if (graph.size() < 4 * bits_per_word)
        return dbmcsa<order_, 4>(graph, params);
    else if (graph.size() < 8 * bits_per_word)
        return dbmcsa<order_, 8>(graph, params);
    else if (graph.size() < 16 * bits_per_word)
        return dbmcsa<order_, 16>(graph, params);
    else if (graph.size() < 32 * bits_per_word)
        return dbmcsa<order_, 32>(graph, params);
    else if (graph.size() < 64 * bits_per_word)
        return dbmcsa<order_, 64>(graph, params);
    else if (graph.size() < 128 * bits_per_word)
        return dbmcsa<order_, 128>(graph, params);
    else if (graph.size() < 256 * bits_per_word)
        return dbmcsa<order_, 256>(graph, params);
    else if (graph.size() < 512 * bits_per_word)
        return dbmcsa<order_, 512>(graph, params);
    else if (graph.size() < 1024 * bits_per_word)
        return dbmcsa<order_, 1024>(graph, params);
    else
        throw GraphTooBig();
}

template auto parasols::dbmcsa_max_clique<MaxCliqueOrder::Degree>(const Graph &, const MaxCliqueParams &) -> MaxCliqueResult;
template auto parasols::dbmcsa_max_clique<MaxCliqueOrder::MinWidth>(const Graph &, const MaxCliqueParams &) -> MaxCliqueResult;
template auto parasols::dbmcsa_max_clique<MaxCliqueOrder::ExDegree>(const Graph &, const MaxCliqueParams &) -> MaxCliqueResult;
template auto parasols::dbmcsa_max_clique<MaxCliqueOrder::DynExDegree>(const Graph &, const MaxCliqueParams &) -> MaxCliqueResult;

<commit_msg>Start a different attempt at making dbmcsa scale<commit_after>/* vim: set sw=4 sts=4 et foldmethod=syntax : */

#include <max_clique/dbmcsa_max_clique.hh>
#include <max_clique/colourise.hh>
#include <max_clique/print_incumbent.hh>
#include <threads/atomic_incumbent.hh>
#include <threads/queue.hh>
#include <graph/degree_sort.hh>
#include <graph/min_width_sort.hh>

#include <algorithm>
#include <list>
#include <functional>
#include <vector>
#include <thread>

using namespace parasols;

namespace
{
    template <unsigned size_>
    struct QueueItem
    {
        FixedBitSet<size_> c;
        FixedBitSet<size_> p;
        unsigned cn;
        std::vector<int> position;
    };

    template <unsigned size_>
    auto found_possible_new_best(const FixedBitGraph<size_> & graph, const std::vector<int> & o,
            const FixedBitSet<size_> & c, int c_popcount,
            const MaxCliqueParams & params, MaxCliqueResult & result, AtomicIncumbent & best_anywhere,
            const std::vector<int> & position) -> void
    {
        if (best_anywhere.update(c_popcount)) {
            result.size = c_popcount;
            result.members.clear();
            for (int i = 0 ; i < graph.size() ; ++i)
                if (c.test(i))
                    result.members.insert(o[i]);
            print_incumbent(params, result.size, position);
        }
    }

    auto bound(unsigned c_popcount, unsigned cn, const MaxCliqueParams & params, AtomicIncumbent & best_anywhere) -> bool
    {
        unsigned best_anywhere_value = best_anywhere.get();
        return (c_popcount + cn <= best_anywhere_value || best_anywhere_value >= params.stop_after_finding);
    }

    template <MaxCliqueOrder order_, unsigned size_>
    auto expand(
            const FixedBitGraph<size_> & graph,
            const std::vector<int> & o,                      // vertex ordering
            Queue<QueueItem<size_> > * const maybe_queue,    // not null if we're populating: enqueue here
            FixedBitSet<size_> & c,                          // current candidate clique
            FixedBitSet<size_> & p,                          // potential additions
            MaxCliqueResult & result,
            const MaxCliqueParams & params,
            AtomicIncumbent & best_anywhere,
            std::vector<int> & position) -> void
    {
        ++result.nodes;

        auto c_popcount = c.popcount();

        // get our coloured vertices
        std::array<unsigned, size_ * bits_per_word> p_order, colours;
        colourise<size_>(graph, p, p_order, colours);

        // for each v in p... (v comes later)
        for (int n = p.popcount() - 1 ; n >= 0 ; --n) {
            ++position.back();

            // bound, timeout or early exit?
            if (bound(c_popcount, colours[n], params, best_anywhere) || params.abort.load())
                return;

            auto v = p_order[n];

            // consider taking v
            c.set(v);
            ++c_popcount;

            // filter p to contain vertices adjacent to v
            FixedBitSet<size_> new_p = p;
            new_p = p;
            graph.intersect_with_row(v, new_p);

            if (new_p.empty()) {
                found_possible_new_best(graph, o, c, c_popcount, params, result, best_anywhere, position);
            }
            else
            {
                // do we enqueue or recurse?
                bool should_expand = true;

                if (maybe_queue && c_popcount == 1) {
                    auto new_position = position;
                    new_position.push_back(0);
                    maybe_queue->enqueue_blocking(QueueItem<size_>{ c, std::move(new_p), colours[n], std::move(new_position) }, params.n_threads);
                    should_expand = false;
                }

                if (should_expand) {
                    position.push_back(0);
                    expand<order_, size_>(graph, o, maybe_queue, c, new_p, result, params, best_anywhere, position);
                    position.pop_back();
                }
            }

            // now consider not taking v
            c.unset(v);
            p.unset(v);
            --c_popcount;
        }
    }

    template <MaxCliqueOrder order_, unsigned size_>
    auto max_clique(const FixedBitGraph<size_> & graph, const std::vector<int> & o, const MaxCliqueParams & params) -> MaxCliqueResult
    {
        Queue<QueueItem<size_> > queue{ params.n_threads, false, false }; // work queue

        MaxCliqueResult result; // global result
        std::mutex result_mutex;

        AtomicIncumbent best_anywhere; // global incumbent
        best_anywhere.update(params.initial_bound);

        std::list<std::thread> threads; // populating thread, and workers

        /* populate */
        threads.push_back(std::thread([&] {
                    MaxCliqueResult tr; // local result

                    FixedBitSet<size_> tc; // local candidate clique
                    tc.resize(graph.size());

                    FixedBitSet<size_> tp; // local potential additions
                    tp.resize(graph.size());
                    tp.set_all();

                    std::vector<int> position;
                    position.reserve(graph.size());
                    position.push_back(0);

                    // populate!
                    expand<order_, size_>(graph, o, &queue, tc, tp, result, params, best_anywhere, position);

                    // merge results
                    queue.initial_producer_done();
                    std::unique_lock<std::mutex> guard(result_mutex);
                    result.merge(tr);
                    }));

        /* workers */
        for (unsigned i = 0 ; i < params.n_threads ; ++i) {
            threads.push_back(std::thread([&, i] {
                        auto start_time = std::chrono::steady_clock::now(); // local start time

                        MaxCliqueResult tr; // local result

                        while (true) {
                            // get some work to do
                            QueueItem<size_> args;
                            if (! queue.dequeue_blocking(args))
                                break;

                            // re-evaluate the bound against our new best
                            if (args.cn <= best_anywhere.get())
                                continue;

                            // do some work
                            expand<order_, size_>(graph, o, nullptr, args.c, args.p, tr, params, best_anywhere, args.position);
                        }

                        auto overall_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time);

                        // merge results
                        {
                            std::unique_lock<std::mutex> guard(result_mutex);
                            result.merge(tr);
                            result.times.push_back(overall_time);
                        }
                        }));
        }

        // wait until they're done, and clean up threads
        for (auto & t : threads)
            t.join();

        return result;
    }

    template <MaxCliqueOrder order_, unsigned size_>
    auto dbmcsa(const Graph & graph, const MaxCliqueParams & params) -> MaxCliqueResult
    {
        std::vector<int> o(graph.size()); // vertex ordering
        std::iota(o.begin(), o.end(), 0);

        switch (order_) {
            case MaxCliqueOrder::Degree:
                degree_sort(graph, o, false);
                break;
            case MaxCliqueOrder::MinWidth:
                min_width_sort(graph, o, false);
                break;
            case MaxCliqueOrder::ExDegree:
                exdegree_sort(graph, o, false);
                break;
            case MaxCliqueOrder::DynExDegree:
                dynexdegree_sort(graph, o, false);
                break;
        }

        // re-encode graph as a bit graph
        FixedBitGraph<size_> bit_graph;
        bit_graph.resize(graph.size());

        for (int i = 0 ; i < graph.size() ; ++i)
            for (int j = 0 ; j < graph.size() ; ++j)
                if (graph.adjacent(o[i], o[j]))
                    bit_graph.add_edge(i, j);

        // go!
        return max_clique<order_>(bit_graph, o, params);
    }
}

template <MaxCliqueOrder order_>
auto parasols::dbmcsa_max_clique(const Graph & graph, const MaxCliqueParams & params) -> MaxCliqueResult
{
    /* This is pretty horrible: in order to avoid dynamic allocation, select
     * the appropriate specialisation for our graph's size. */
    static_assert(max_graph_words == 1024, "Need to update here if max_graph_size is changed.");
    if (graph.size() < bits_per_word)
        return dbmcsa<order_, 1>(graph, params);
    else if (graph.size() < 2 * bits_per_word)
        return dbmcsa<order_, 2>(graph, params);
    else if (graph.size() < 4 * bits_per_word)
        return dbmcsa<order_, 4>(graph, params);
    else if (graph.size() < 8 * bits_per_word)
        return dbmcsa<order_, 8>(graph, params);
    else if (graph.size() < 16 * bits_per_word)
        return dbmcsa<order_, 16>(graph, params);
    else if (graph.size() < 32 * bits_per_word)
        return dbmcsa<order_, 32>(graph, params);
    else if (graph.size() < 64 * bits_per_word)
        return dbmcsa<order_, 64>(graph, params);
    else if (graph.size() < 128 * bits_per_word)
        return dbmcsa<order_, 128>(graph, params);
    else if (graph.size() < 256 * bits_per_word)
        return dbmcsa<order_, 256>(graph, params);
    else if (graph.size() < 512 * bits_per_word)
        return dbmcsa<order_, 512>(graph, params);
    else if (graph.size() < 1024 * bits_per_word)
        return dbmcsa<order_, 1024>(graph, params);
    else
        throw GraphTooBig();
}

template auto parasols::dbmcsa_max_clique<MaxCliqueOrder::Degree>(const Graph &, const MaxCliqueParams &) -> MaxCliqueResult;
template auto parasols::dbmcsa_max_clique<MaxCliqueOrder::MinWidth>(const Graph &, const MaxCliqueParams &) -> MaxCliqueResult;
template auto parasols::dbmcsa_max_clique<MaxCliqueOrder::ExDegree>(const Graph &, const MaxCliqueParams &) -> MaxCliqueResult;
template auto parasols::dbmcsa_max_clique<MaxCliqueOrder::DynExDegree>(const Graph &, const MaxCliqueParams &) -> MaxCliqueResult;

<|endoftext|>


<commit_before>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2012 Scientific Computing and Imaging Institute,
   University of Utah.

   License for the specific language governing rights and limitations under
   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/

#include <Core/Algorithms/Legacy/Fields/FieldData/BuildMatrixOfSurfaceNormalsAlgo.h>
#include <Core/Algorithms/Base/AlgorithmPreconditions.h>
#include <Core/Algorithms/Base/AlgorithmVariableNames.h>
//#include <Core/GeometryPrimitives/Vector.h>
#include <Core/Datatypes/Legacy/Field/Field.h>
#include <Core/Datatypes/Legacy/Field/VField.h>
#include <Core/Datatypes/DenseMatrix.h>
#include <Core/GeometryPrimitives/Vector.h>
#include <Core/Datatypes/Legacy/Matrix/Matrix.h>
#include <Core/Datatypes/Legacy/Field/FieldInformation.h>

//#include <Core/Datatypes/DenseMatrix.h>
//#include <Core/Datatypes/Legacy/Field/VMesh.h>

//#include <iostream>

using namespace SCIRun::Core::Algorithms;
using namespace SCIRun::Core::Algorithms::Fields;
using namespace SCIRun::Core::Datatypes;
using namespace SCIRun::Core::Geometry;
using namespace SCIRun::Core::Logging;
using namespace SCIRun::Core::Utility;
using namespace SCIRun;

BuildMatrixOfSurfaceNormalsAlgo::BuildMatrixOfSurfaceNormalsAlgo() {}

bool BuildMatrixOfSurfaceNormalsAlgo::runImpl(FieldHandle input, DenseMatrixHandle& output) const
{
	ScopedAlgorithmStatusReporter asr(this, "SetFieldDataToConstantValue");

  if (!input)
  {
    error("No input source field");
    return (false);
  }

  FieldInformation fi(input);
  if (!(fi.is_surface()))
  {
    error("This algorithm only works on a surface mesh");
    return (false);
  }

  VMesh* vmesh = input->vmesh();
  vmesh->synchronize(Mesh::NORMALS_E);
  VMesh::size_type num_nodes = vmesh->num_nodes();

  output.reset(new DenseMatrix(num_nodes, 3));

  if (!output)
  {
    error("Could not allocate output matrix");
    return (false);
  }

  index_type k = 0;
  int cnt = 0;
  Vector norm;
  for (VMesh::Node::index_type i=0; i<num_nodes; ++i)
  {
    vmesh->get_normal(norm,i);
    (*output)(i,k) = norm.x();
		(*output)(i,k+1) = norm.y();
		(*output)(i,k+2) = norm.z();
    k += 3;
    cnt++; if (cnt == 400) {cnt=0; update_progress_max(i,num_nodes); }
  }

  return (true);
}

AlgorithmOutput BuildMatrixOfSurfaceNormalsAlgo::run_generic(const AlgorithmInput& input) const
{
  auto field = input.get<Field>(Variables::InputField);
	DenseMatrixHandle outputField;

	if(!runImpl(field, outputField))
			THROW_ALGORITHM_PROCESSING_ERROR("False returned on legacy call.");

  AlgorithmOutput output;
  output[Variables::OutputField] = outputField;
  return output;
}<commit_msg>Unsure why output isn't being passed<commit_after>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2012 Scientific Computing and Imaging Institute,
   University of Utah.

   License for the specific language governing rights and limitations under
   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/

#include <Core/Algorithms/Legacy/Fields/FieldData/BuildMatrixOfSurfaceNormalsAlgo.h>
#include <Core/Algorithms/Base/AlgorithmPreconditions.h>
#include <Core/Algorithms/Base/AlgorithmVariableNames.h>
//#include <Core/GeometryPrimitives/Vector.h>
#include <Core/Datatypes/Legacy/Field/Field.h>
#include <Core/Datatypes/Legacy/Field/VField.h>
#include <Core/Datatypes/DenseMatrix.h>
#include <Core/GeometryPrimitives/Vector.h>
#include <Core/Datatypes/Legacy/Matrix/Matrix.h>
#include <Core/Datatypes/Legacy/Field/FieldInformation.h>

//#include <Core/Datatypes/DenseMatrix.h>
//#include <Core/Datatypes/Legacy/Field/VMesh.h>

//#include <iostream>

using namespace SCIRun::Core::Algorithms;
using namespace SCIRun::Core::Algorithms::Fields;
using namespace SCIRun::Core::Datatypes;
using namespace SCIRun::Core::Geometry;
using namespace SCIRun::Core::Logging;
using namespace SCIRun::Core::Utility;
using namespace SCIRun;

BuildMatrixOfSurfaceNormalsAlgo::BuildMatrixOfSurfaceNormalsAlgo() {}

bool BuildMatrixOfSurfaceNormalsAlgo::runImpl(FieldHandle input, DenseMatrixHandle& output) const
{
	ScopedAlgorithmStatusReporter asr(this, "SetFieldDataToConstantValue");

  if (!input)
  {
    error("No input source field");
    return (false);
  }

  FieldInformation fi(input);
  if (!(fi.is_surface()))
  {
    error("This algorithm only works on a surface mesh");
    return (false);
  }

  VMesh* vmesh = input->vmesh();
  vmesh->synchronize(Mesh::NORMALS_E);
  VMesh::size_type num_nodes = vmesh->num_nodes();

  output.reset(new DenseMatrix(num_nodes, 3));

  if (!output)
  {
    error("Could not allocate output matrix");
    return (false);
  }

	VMesh::Node::index_type k = 0;
  int cnt = 0;
  Vector norm;
  for (VMesh::Node::index_type i=0; i<num_nodes; ++i)
  {
    vmesh->get_normal(norm,i);
    (*output)(k) = norm.x();
		(*output)(k+1) = norm.y();
		(*output)(k+2) = norm.z();
    k += 3;
    cnt++; if (cnt == 400) {cnt=0; update_progress_max(i,num_nodes); }
  }
  return (true);
}

AlgorithmOutput BuildMatrixOfSurfaceNormalsAlgo::run_generic(const AlgorithmInput& input) const
{
  auto field = input.get<Field>(Variables::InputField);
	DenseMatrixHandle outputMatrix;

	if(!runImpl(field, outputMatrix))
			THROW_ALGORITHM_PROCESSING_ERROR("False returned on legacy call.");

  AlgorithmOutput output;
  output[Variables::OutputMatrix] = outputMatrix;
  return output;
}<|endoftext|>


<commit_before>#include <iostream>
#include <vpp/vpp.hh>

#include <iod/sio.hh>
#include <iod/sio_utils.hh>
#include <iod/foreach.hh>
#include <iod/grammar.hh>
#include <iod/grammar_utils.hh>
#include <iod/symbols.hh>

#include <vpp/core/pixel_wise.hh>
#include <vpp/core/liie.hh>

using namespace vpp;
using namespace vpp::liie;
using namespace s;

int main()
{
  image2d<int> A(10,10);
  image2d<int> B(10,10);
  const image2d<int> C(10,10);

  // A + B;
  fill(A, 1);
  fill(B, 2);

  A(5,5) = 1000;

  auto X = pixel_wise(A, B).eval(_V(A) = _V(A) + _V(_2));

  assert(eval(A, B, A, _Argmax(_V(A))) == vint2(5,5));
  assert(eval(_Argmax(_V(A))) == vint2(5,5));
  assert(eval(A, _Argmax(_V(_1))) == vint2(5,5));

  X = eval(_V(A) + _V(B));
  assert(X(0,0) == 3);

  eval(_V(X) = _V(B) * 2);
  assert(X(0,0) == 4);

  eval(X, _V(_1) = _V(B) * 2);
  assert(X(0,0) == 4);

  assert(eval(_Max(A)) == 1000);
  assert(eval(_Min(A)) == 1);
}
<commit_msg>Fix liie test.<commit_after>#include <iostream>
#include <vpp/vpp.hh>

#include <iod/sio.hh>
#include <iod/sio_utils.hh>
#include <iod/foreach.hh>
#include <iod/grammar.hh>
#include <iod/grammar_utils.hh>
#include <iod/symbols.hh>

#include <vpp/core/pixel_wise.hh>
#include <vpp/core/liie.hh>

using namespace vpp;
using namespace vpp::liie;
using namespace s;

int main()
{
  image2d<int> A(10,10);
  image2d<int> B(10,10);
  const image2d<int> C(10,10);

  // A + B;
  fill(A, 1);
  fill(B, 2);

  A(5,5) = 1000;

  auto X = pixel_wise(A, B).eval(_V(A) = _V(A) + _V(_2));

  assert(eval(A, B, A, _Argmax(_V(A))) == vint2(5,5));
  assert(eval(_Argmax(_V(A))) == vint2(5,5));
  assert(eval(A, _Argmax(_V(_1))) == vint2(5,5));

  fill(A, 1); fill(B, 2);
  X = eval(_V(A) + _V(B));
  assert(X(0,0) == 3);

  eval(_V(X) = _V(B) * 2);
  assert(X(0,0) == 4);

  eval(X, _V(_1) = _V(B) * 2);
  assert(X(0,0) == 4);

  A(5,5) = 1000;
  A(2,5) = -11;
  assert(eval(_Max(A)) == 1000);
  assert(eval(_Min(A)) == -11);
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** If you have questions regarding the use of this file, please
** contact Nokia at http://www.qtsoftware.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qmessagestore.h"
#include "qmfhelpers_p.h"

#include <qmailstore.h>

using namespace QmfHelpers;

class QMessageStorePrivate
{
public:
    QMessageStorePrivate() : _store(QMailStore::instance()) {}

    QMailStore *_store;

    Q_SCOPED_STATIC_DECLARE(QMessageStore,storeInstance);
};

Q_SCOPED_STATIC_DEFINE(QMessageStore,QMessageStorePrivate,storeInstance);

QMessageStore::QMessageStore(QObject *parent)
    : QObject(parent),
      d_ptr(new QMessageStorePrivate)
{
    Q_ASSERT(instance() != 0);
}

QMessageStore::~QMessageStore()
{
    delete d_ptr;
}

QMessageStore::ErrorCode QMessageStore::lastError() const
{
    return NotYetImplemented;
}

QMessageIdList QMessageStore::queryMessages(const QMessageFilterKey &key, const QMessageSortKey &sortKey, uint limit, uint offset) const
{
    Q_UNUSED(key)
    Q_UNUSED(sortKey)
    Q_UNUSED(limit)
    Q_UNUSED(offset)
    return QMessageIdList(); // stub
}

#ifdef QMESSAGING_OPTIONAL_FOLDER
QMessageFolderIdList QMessageStore::queryFolders(const QMessageFolderFilterKey &key, const QMessageFolderSortKey &sortKey, uint limit, uint offset) const
{
    Q_UNUSED(key)
    Q_UNUSED(sortKey)
    Q_UNUSED(limit)
    Q_UNUSED(offset)
    return QMessageFolderIdList(); // stub
}
#endif

QMessageAccountIdList QMessageStore::queryAccounts(const QMessageAccountFilterKey &key, const QMessageAccountSortKey &sortKey, uint limit, uint offset) const
{
    Q_UNUSED(key)
    Q_UNUSED(sortKey)
    Q_UNUSED(limit)
    Q_UNUSED(offset)
    return QMessageAccountIdList(); // stub
}

int QMessageStore::countMessages(const QMessageFilterKey& key) const
{
    Q_UNUSED(key)
    return 0; // stub
}

#ifdef QMESSAGING_OPTIONAL_FOLDER
int QMessageStore::countFolders(const QMessageFolderFilterKey& key) const
{
    Q_UNUSED(key)
    return 0; // stub
}
#endif

int QMessageStore::countAccounts(const QMessageAccountFilterKey& key) const
{
    Q_UNUSED(key)
    return 0; // stub
}

bool QMessageStore::removeMessage(const QMessageId& id, RemovalOption option)
{
    Q_UNUSED(id)
    Q_UNUSED(option)
    return false; // stub
}

bool QMessageStore::removeMessages(const QMessageFilterKey& key, QMessageStore::RemovalOption option)
{
    Q_UNUSED(key)
    Q_UNUSED(option)
    return true; // stub
}

bool QMessageStore::addMessage(QMessage *m)
{
    Q_UNUSED(m)
    return true; // stub
}

bool QMessageStore::updateMessage(QMessage *m)
{
    Q_UNUSED(m)
    return true; // stub
}

QMessage QMessageStore::message(const QMessageId& id) const
{
    Q_UNUSED(id)
    return QMessage(); // stub
}

#ifdef QMESSAGING_OPTIONAL_FOLDER
QMessageFolder QMessageStore::folder(const QMessageFolderId& id) const
{
    Q_UNUSED(id)
    return QMessageFolder(); // stub
}
#endif

QMessageAccount QMessageStore::account(const QMessageAccountId& id) const
{
    Q_UNUSED(id)
    return QMessageAccount(); // stub
}

void QMessageStore::setMaximumWorkingMemory(uint maximumBytes)
{
    Q_UNUSED(maximumBytes)
}

uint QMessageStore::maximumWorkingMemory()
{
    return 0; // stub
}

QMessageStore* QMessageStore::instance()
{
    return QMessageStorePrivate::storeInstance();
}

void QMessageStore::startNotifications(const QMessageFilterKey &key)
{
    Q_UNUSED(key)
}

void QMessageStore::stopNotifications()
{
}
<commit_msg>Minimal implementation of QMessageStore for QMF.<commit_after>/****************************************************************************
**
** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** If you have questions regarding the use of this file, please
** contact Nokia at http://www.qtsoftware.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qmessagestore.h"
#include "qmfhelpers_p.h"

#include <qmailstore.h>

using namespace QmfHelpers;

class QMessageStorePrivate
{
public:
    QMessageStorePrivate() : _store(QMailStore::instance()), _error(QMessageStore::NoError) {}

    QMailStore *_store;
    QMessageStore::ErrorCode _error;

    Q_SCOPED_STATIC_DECLARE(QMessageStore,storeInstance);
};

Q_SCOPED_STATIC_DEFINE(QMessageStore,QMessageStorePrivate,storeInstance);

QMessageStore::QMessageStore(QObject *parent)
    : QObject(parent),
      d_ptr(new QMessageStorePrivate)
{
    Q_ASSERT(instance() != 0);
}

QMessageStore::~QMessageStore()
{
    delete d_ptr;
}

QMessageStore::ErrorCode QMessageStore::lastError() const
{
    if (d_ptr->_error != QMessageStore::NoError) {
        return d_ptr->_error;
    }

    return convert(d_ptr->_store->lastError());
}

QMessageIdList QMessageStore::queryMessages(const QMessageFilterKey &key, const QMessageSortKey &sortKey, uint limit, uint offset) const
{
    if (key.options() != 0) {
        d_ptr->_error = QMessageStore::NotYetImplemented;
        return QMessageIdList();
    }

    d_ptr->_error = QMessageStore::NoError;
    return convert(d_ptr->_store->queryMessages(convert(key), convert(sortKey)));

    // TODO: Extend QMF to support limit/offset
    Q_UNUSED(limit)
    Q_UNUSED(offset)
}

#ifdef QMESSAGING_OPTIONAL_FOLDER
QMessageFolderIdList QMessageStore::queryFolders(const QMessageFolderFilterKey &key, const QMessageFolderSortKey &sortKey, uint limit, uint offset) const
{
    if (key.options() != 0) {
        d_ptr->_error = QMessageStore::NotYetImplemented;
        return QMessageFolderIdList();
    }

    d_ptr->_error = QMessageStore::NoError;
    return convert(d_ptr->_store->queryFolders(convert(key), convert(sortKey)));

    // TODO: Extend QMF to support limit/offset
    Q_UNUSED(limit)
    Q_UNUSED(offset)
}
#endif

QMessageAccountIdList QMessageStore::queryAccounts(const QMessageAccountFilterKey &key, const QMessageAccountSortKey &sortKey, uint limit, uint offset) const
{
    if (key.options() != 0) {
        d_ptr->_error = QMessageStore::NotYetImplemented;
        return QMessageAccountIdList();
    }

    d_ptr->_error = QMessageStore::NoError;
    return convert(d_ptr->_store->queryAccounts(convert(key), convert(sortKey)));

    // TODO: Extend QMF to support limit/offset
    Q_UNUSED(limit)
    Q_UNUSED(offset)
}

int QMessageStore::countMessages(const QMessageFilterKey& key) const
{
    if (key.options() != 0) {
        d_ptr->_error = QMessageStore::NotYetImplemented;
        return 0;
    }

    d_ptr->_error = QMessageStore::NoError;
    return d_ptr->_store->countMessages(convert(key));
}

#ifdef QMESSAGING_OPTIONAL_FOLDER
int QMessageStore::countFolders(const QMessageFolderFilterKey& key) const
{
    if (key.options() != 0) {
        d_ptr->_error = QMessageStore::NotYetImplemented;
        return 0;
    }

    d_ptr->_error = QMessageStore::NoError;
    return d_ptr->_store->countFolders(convert(key));
}
#endif

int QMessageStore::countAccounts(const QMessageAccountFilterKey& key) const
{
    if (key.options() != 0) {
        d_ptr->_error = QMessageStore::NotYetImplemented;
        return 0;
    }

    d_ptr->_error = QMessageStore::NoError;
    return d_ptr->_store->countAccounts(convert(key));
}

bool QMessageStore::removeMessage(const QMessageId& id, QMessageStore::RemovalOption option)
{
    d_ptr->_error = QMessageStore::NoError;
    return d_ptr->_store->removeMessage(convert(id), convert(option));
}

bool QMessageStore::removeMessages(const QMessageFilterKey& key, QMessageStore::RemovalOption option)
{
    d_ptr->_error = QMessageStore::NoError;
    return d_ptr->_store->removeMessages(convert(key), convert(option));
}

bool QMessageStore::addMessage(QMessage *m)
{
    QMailMessage msg(convert(*m));

    d_ptr->_error = QMessageStore::NoError;
    return d_ptr->_store->addMessage(&msg);
}

bool QMessageStore::updateMessage(QMessage *m)
{
    QMailMessage msg(convert(*m));

    d_ptr->_error = QMessageStore::NoError;
    return d_ptr->_store->updateMessage(&msg);
}

QMessage QMessageStore::message(const QMessageId& id) const
{
    d_ptr->_error = QMessageStore::NoError;
    return convert(d_ptr->_store->message(convert(id)));
}

#ifdef QMESSAGING_OPTIONAL_FOLDER
QMessageFolder QMessageStore::folder(const QMessageFolderId& id) const
{
    d_ptr->_error = QMessageStore::NoError;
    return convert(d_ptr->_store->folder(convert(id)));
}
#endif

QMessageAccount QMessageStore::account(const QMessageAccountId& id) const
{
    d_ptr->_error = QMessageStore::NoError;
    return convert(d_ptr->_store->account(convert(id)));
}

void QMessageStore::setMaximumWorkingMemory(uint maximumBytes)
{
    // TODO: implement memory constraints
    Q_UNUSED(maximumBytes)
}

uint QMessageStore::maximumWorkingMemory()
{
    // TODO: implement memory constraints
    return 0; // stub
}

QMessageStore* QMessageStore::instance()
{
    return QMessageStorePrivate::storeInstance();
}

void QMessageStore::startNotifications(const QMessageFilterKey &key)
{
    if (key.options() != 0) {
        d_ptr->_error = QMessageStore::NotYetImplemented;
        return;
    }

    // TODO: implement notifications
    Q_UNUSED(key)
}

void QMessageStore::stopNotifications()
{
    // TODO: implement notifications
}

<|endoftext|>


<commit_before>#ifndef _IRDEBUG_HPP
#define _IRDEBUG_HPP

#include <llvm/IR/Module.h>
#include <llvm/IR/LLVMContext.h>

#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 5
#include <llvm/IR/DIBuilder.h>
#endif

#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR <= 4
#include <llvm/DIBuilder.h>
#include <llvm/DebugInfo.h>
#endif

#include "irCodegenContext.hpp"
#include "ast.hpp"

#include <string>
#include <map>

#define CGSTR "wlc 0.22 - Oct 2014"
#define PROJDIR "/home/brandon/PROJECTS/C/term/wlc"

class IRCodegenContext;
struct IRTranslationUnit;
class IRDebug
{
    public:
        IRCodegenContext *context;
        IRTranslationUnit *unit;
        llvm::DIBuilder di;
        llvm::DIFile diFile;
        llvm::DICompileUnit diUnit;

        // map for complex types
        // index is mangled name
        std::map<std::string, llvm::DIType> typeMap;

        IRDebug(IRCodegenContext *c, IRTranslationUnit *u);

        ~IRDebug()
        {
            finalize();
        }

        void finalize()
        {
            di.finalize();
        }

        llvm::Module *getModule();

        llvm::DICompileUnit getCompileUnit() { return diUnit; }
        llvm::DIFile currentFile() { return diFile; }
        llvm::DIDescriptor currentScope();
        llvm::DIDescriptor createScope(llvm::DIDescriptor parent, SourceLocation loc);
        llvm::DIType createClassType(ASTType *ty);
        llvm::DICompositeType createUserType(ASTType *ty);
        llvm::DICompositeType createStructType(ASTType *ty);
        llvm::DICompositeType createUnionType(ASTType *ty);
        llvm::DICompositeType createDynamicArrayType(ASTType *ty);
        llvm::DICompositeType createArrayType(ASTType *ty);
        llvm::DICompositeType createTupleType(ASTType *ty);
        llvm::DIType createType(ASTType *t);
        llvm::DICompositeType createPrototype(ASTType *p);
        llvm::DISubprogram createFunction(FunctionDeclaration *f, llvm::Function *cgFunc);
        llvm::DIGlobalVariable createGlobal(VariableDeclaration *decl, ASTValue *val);
        llvm::Instruction *createVariable(std::string nm, ASTValue *v,
                llvm::BasicBlock *bb, SourceLocation loc, int argn = 0);
};

void createIdentMetadata(llvm::Module *m);

#endif
<commit_msg>updated version string to 0.23 - Dec<commit_after>#ifndef _IRDEBUG_HPP
#define _IRDEBUG_HPP

#include <llvm/IR/Module.h>
#include <llvm/IR/LLVMContext.h>

#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 5
#include <llvm/IR/DIBuilder.h>
#endif

#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR <= 4
#include <llvm/DIBuilder.h>
#include <llvm/DebugInfo.h>
#endif

#include "irCodegenContext.hpp"
#include "ast.hpp"

#include <string>
#include <map>

#define CGSTR "wlc 0.22 - Dec 2014"
#define PROJDIR "/home/brandon/PROJECTS/C/term/wlc"

class IRCodegenContext;
struct IRTranslationUnit;
class IRDebug
{
    public:
        IRCodegenContext *context;
        IRTranslationUnit *unit;
        llvm::DIBuilder di;
        llvm::DIFile diFile;
        llvm::DICompileUnit diUnit;

        // map for complex types
        // index is mangled name
        std::map<std::string, llvm::DIType> typeMap;

        IRDebug(IRCodegenContext *c, IRTranslationUnit *u);

        ~IRDebug()
        {
            finalize();
        }

        void finalize()
        {
            di.finalize();
        }

        llvm::Module *getModule();

        llvm::DICompileUnit getCompileUnit() { return diUnit; }
        llvm::DIFile currentFile() { return diFile; }
        llvm::DIDescriptor currentScope();
        llvm::DIDescriptor createScope(llvm::DIDescriptor parent, SourceLocation loc);
        llvm::DIType createClassType(ASTType *ty);
        llvm::DICompositeType createUserType(ASTType *ty);
        llvm::DICompositeType createStructType(ASTType *ty);
        llvm::DICompositeType createUnionType(ASTType *ty);
        llvm::DICompositeType createDynamicArrayType(ASTType *ty);
        llvm::DICompositeType createArrayType(ASTType *ty);
        llvm::DICompositeType createTupleType(ASTType *ty);
        llvm::DIType createType(ASTType *t);
        llvm::DICompositeType createPrototype(ASTType *p);
        llvm::DISubprogram createFunction(FunctionDeclaration *f, llvm::Function *cgFunc);
        llvm::DIGlobalVariable createGlobal(VariableDeclaration *decl, ASTValue *val);
        llvm::Instruction *createVariable(std::string nm, ASTValue *v,
                llvm::BasicBlock *bb, SourceLocation loc, int argn = 0);
};

void createIdentMetadata(llvm::Module *m);

#endif
<|endoftext|>


<commit_before>/*
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "isolate.hxx"
#include "system/pivot_root.h"

#include <daemon/log.h>

#include <sched.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/mount.h>
#include <sys/stat.h>

#if !defined(MS_PRIVATE) && !defined(MS_REC)
/* necessary on Debian Squeeze */
#include <linux/fs.h>
#endif

#ifndef __linux
#error This library requires Linux
#endif

void
isolate_from_filesystem()
{
    constexpr int flags = CLONE_NEWUSER|CLONE_NEWNS;
    if (unshare(flags) < 0) {
        daemon_log(3, "unshare(0x%x) failed: %s\n", flags, strerror(errno));
        return;
    }

    /* convert all "shared" mounts to "private" mounts */
    mount(nullptr, "/", nullptr, MS_PRIVATE|MS_REC, nullptr);

    const char *const new_root = "/tmp";
    const char *const put_old = "old";

    if (mount(nullptr, new_root, "tmpfs", MS_NODEV|MS_NOEXEC|MS_NOSUID,
              "size=16k,nr_inodes=16,mode=700") < 0) {
        daemon_log(3, "failed to mount tmpfs: %s\n", strerror(errno));
        return;
    }

    /* release a reference to the old root */
    if (chdir(new_root) < 0) {
        fprintf(stderr, "chdir('%s') failed: %s\n",
                new_root, strerror(errno));
        _exit(2);
    }

    mkdir(put_old, 0);

    /* enter the new root */
    if (my_pivot_root(new_root, put_old) < 0) {
        fprintf(stderr, "pivot_root('%s') failed: %s\n",
                new_root, strerror(errno));
        _exit(2);
    }

    /* get rid of the old root */
    if (umount2(put_old, MNT_DETACH) < 0) {
        fprintf(stderr, "umount('%s') failed: %s",
                put_old, strerror(errno));
        _exit(2);
    }

    rmdir(put_old);
}
<commit_msg>isolate: drop read permissions on "/"<commit_after>/*
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "isolate.hxx"
#include "system/pivot_root.h"

#include <daemon/log.h>

#include <sched.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/mount.h>
#include <sys/stat.h>

#if !defined(MS_PRIVATE) && !defined(MS_REC)
/* necessary on Debian Squeeze */
#include <linux/fs.h>
#endif

#ifndef __linux
#error This library requires Linux
#endif

void
isolate_from_filesystem()
{
    constexpr int flags = CLONE_NEWUSER|CLONE_NEWNS;
    if (unshare(flags) < 0) {
        daemon_log(3, "unshare(0x%x) failed: %s\n", flags, strerror(errno));
        return;
    }

    /* convert all "shared" mounts to "private" mounts */
    mount(nullptr, "/", nullptr, MS_PRIVATE|MS_REC, nullptr);

    const char *const new_root = "/tmp";
    const char *const put_old = "old";

    if (mount(nullptr, new_root, "tmpfs", MS_NODEV|MS_NOEXEC|MS_NOSUID,
              "size=16k,nr_inodes=16,mode=700") < 0) {
        daemon_log(3, "failed to mount tmpfs: %s\n", strerror(errno));
        return;
    }

    /* release a reference to the old root */
    if (chdir(new_root) < 0) {
        fprintf(stderr, "chdir('%s') failed: %s\n",
                new_root, strerror(errno));
        _exit(2);
    }

    mkdir(put_old, 0);

    /* enter the new root */
    if (my_pivot_root(new_root, put_old) < 0) {
        fprintf(stderr, "pivot_root('%s') failed: %s\n",
                new_root, strerror(errno));
        _exit(2);
    }

    /* get rid of the old root */
    if (umount2(put_old, MNT_DETACH) < 0) {
        fprintf(stderr, "umount('%s') failed: %s",
                put_old, strerror(errno));
        _exit(2);
    }

    rmdir(put_old);

    chmod("/", 0111);
}
<|endoftext|>


<commit_before>/*
 * Loconet over TCP to Codeline
 */

#include "application.h"
#include "codeline_lntcp/codeline_lntcp.h"

typedef struct peerxfer_t {
    uint8_t command;
    uint8_t mesg_size;     /* ummmmm, size of the message in bytes?                */
    uint8_t src;           /* source of transfer                                   */
    uint8_t dst_l;         /* ls 7 bits of destination                             */
    uint8_t dst_h;         /* ms 7 bits of destination                             */
    uint8_t pxct1;
    uint8_t d1;            /* data byte 1                                          */
    uint8_t d2;            /* data byte 2                                          */
    uint8_t d3;            /* data byte 3                                          */
    uint8_t d4;            /* data byte 4                                          */
    uint8_t pxct2;
    uint8_t d5;            /* data byte 5                                          */
    uint8_t d6;            /* data byte 6                                          */
    uint8_t d7;            /* data byte 7                                          */
    uint8_t d8;            /* data byte 8                                          */
    uint8_t chksum;        /* exclusive-or checksum for the message                */
} peerXferMsg;

// SV1 must have the upper nibbles of pxct1 = 0x0x and pxct2 = 0x1x
// SV2 must have the upper nibbles of pxct1 = 0x1x and pxct2 = 0x1x

// Use a reserved bit from pxct1 to indicate packets that we routed,
// so we ignore them when reflected/retransmitted

// SPCoast codeline uses ONLY SV1 format packets, SO WE CAN "REUSE" THIS RESERVED BIT.
// This DOES mean that no SV2-style devices can be allowed on this loconet.

void codeline_lntcp::code2LN(char *s, int *code, int src, int dst) {
    char data[17];
	data[ 0 ] = codeline_lntcp::OPC_PEER_XFER ;
	data[ 1 ] = 0x10;               // packet length = 16
	data[ 2 ] = (src & 0x7F);       // SRC
	data[ 3 ] = (dst & 0x7F);       // DSTL
	data[ 4 ] = 0x00;               // must be 0x01 - 00=JMP debug

	int pxct = codeline_lntcp::PXCT1_RESERVED;
	if (code[0] & 0x80) pxct |= 0b0001;
	if (code[1] & 0x80) pxct |= 0b0010;
	if (code[2] & 0x80) pxct |= 0b0100;
	if (code[3] & 0x80) pxct |= 0b1000;

	data[ 5 ] =  pxct;    // pxct1
	data[ 6 ] = code[0] & 0x7F;
	data[ 7 ] = code[1] & 0x7F;
	data[ 8 ] = code[2] & 0x7F;
	data[ 9 ] = code[3] & 0x7F;

	pxct = 0x10;
	if (code[4] & 0x80) pxct |= 0b0001;
	if (code[5] & 0x80) pxct |= 0b0010;
	if (code[6] & 0x80) pxct |= 0b0100;
	if (code[7] & 0x80) pxct |= 0b1000;

	data[ 10 ] = pxct;    // pxct2
	data[ 11 ] = code[4] & 0x7F;
	data[ 12 ] = code[5] & 0x7F;
	data[ 13 ] = code[6] & 0x7F;
	data[ 14 ] = code[7] & 0x7F;

    byte checksum = 0xFF;
	for (int i = 0; i < 15; i++) {
      checksum ^= data[i];
    }
    data[ 15 ] = checksum; //checksum

    sprintf(s, "SEND %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
            data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15]);
}

// convenience wrapper arround strtok() - call first time with a string, the rest with NULL
unsigned codeline_lntcp::getValue(char *s) {
    static char buffer4strtok[80];
    char* myCopy;
    if (s) {
        strcpy(buffer4strtok, s);
        myCopy = strtok(buffer4strtok, " ");
    } else {
        myCopy = strtok(NULL, " ");
    }
    return strtoul(myCopy, 0, 16);
}

// Parse a LoconetOverTCP string into components,
// grab 8 data bytes and load into code array
// This is probably better done with sscanf()
int codeline_lntcp::LN2code(char *s, int *code, int *opcode, int *src, int *dst) {
    peerXferMsg pkt;
    *opcode  = getValue(s);

    if (*opcode == codeline_lntcp::OPC_PEER_XFER) {
        pkt.command   = *opcode;
        pkt.mesg_size = getValue(NULL);
        pkt.src       = getValue(NULL);     // source of transfer (0x00-0x7F)
        pkt.dst_l     = getValue(NULL);     // destination  (0x00-0x7F)
        pkt.dst_h     = getValue(NULL);     // must be 0x01
        pkt.pxct1     = getValue(NULL);     //
        pkt.d1        = getValue(NULL);     // data byte 1
        pkt.d2        = getValue(NULL);     // data byte 2
        pkt.d3        = getValue(NULL);     // data byte 3
        pkt.d4        = getValue(NULL);     // data byte 4
        pkt.pxct2     = getValue(NULL);
        pkt.d5        = getValue(NULL);     // data byte 5
        pkt.d6        = getValue(NULL);     // data byte 6
        pkt.d7        = getValue(NULL);     // data byte 7
        pkt.d8        = getValue(NULL);     // data byte 8
        pkt.chksum    = getValue(NULL);     // exclusive-or checksum for the message

        *src = (byte)pkt.src   & 0x7f;
	    *dst = (byte)pkt.dst_l & 0x7f;
        code[0] = (byte)pkt.d1;
        code[1] = (byte)pkt.d2;
        code[2] = (byte)pkt.d3;
        code[3] = (byte)pkt.d4;
        code[4] = (byte)pkt.d5;
        code[5] = (byte)pkt.d6;
        code[6] = (byte)pkt.d7;
        code[7] = (byte)pkt.d8;
        if ((byte)pkt.pxct1 & 0b00000001) code[0] |= 0b10000000;
        if ((byte)pkt.pxct1 & 0b00000010) code[1] |= 0b10000000;
        if ((byte)pkt.pxct1 & 0b00000100) code[2] |= 0b10000000;
        if ((byte)pkt.pxct1 & 0b00001000) code[3] |= 0b10000000;

        if ((byte)pkt.pxct2 & 0b00000001) code[4] |= 0b10000000;
        if ((byte)pkt.pxct2 & 0b00000010) code[5] |= 0b10000000;
        if ((byte)pkt.pxct2 & 0b00000100) code[6] |= 0b10000000;
        if ((byte)pkt.pxct2 & 0b00001000) code[7] |= 0b10000000;

        if (((byte)pkt.pxct1 & PXCT1_RESERVED) == PXCT1_RESERVED) { // If the "don't route" bit is set...
            // SV1 must have the upper nibbles of pxct1 = 0x0x and pxct2 = 0x1x
            // FORCE all packets to look like SV1
            pkt.pxct1 = (pkt.pxct1 & 0X0F) | 0X00;
            pkt.pxct2 = (pkt.pxct2 & 0X0F) | 0X10;
            return SEEN;
        } else {
            return ROUTE;
        }
    }
    return IGNORE;
}

<commit_msg>_ becomes - in filenames - grrr<commit_after>/*
 * Loconet over TCP to Codeline
 */

#include "application.h"
#include "codeline-lntcp/codeline-lntcp.h"

typedef struct peerxfer_t {
    uint8_t command;
    uint8_t mesg_size;     /* ummmmm, size of the message in bytes?                */
    uint8_t src;           /* source of transfer                                   */
    uint8_t dst_l;         /* ls 7 bits of destination                             */
    uint8_t dst_h;         /* ms 7 bits of destination                             */
    uint8_t pxct1;
    uint8_t d1;            /* data byte 1                                          */
    uint8_t d2;            /* data byte 2                                          */
    uint8_t d3;            /* data byte 3                                          */
    uint8_t d4;            /* data byte 4                                          */
    uint8_t pxct2;
    uint8_t d5;            /* data byte 5                                          */
    uint8_t d6;            /* data byte 6                                          */
    uint8_t d7;            /* data byte 7                                          */
    uint8_t d8;            /* data byte 8                                          */
    uint8_t chksum;        /* exclusive-or checksum for the message                */
} peerXferMsg;

// SV1 must have the upper nibbles of pxct1 = 0x0x and pxct2 = 0x1x
// SV2 must have the upper nibbles of pxct1 = 0x1x and pxct2 = 0x1x

// Use a reserved bit from pxct1 to indicate packets that we routed,
// so we ignore them when reflected/retransmitted

// SPCoast codeline uses ONLY SV1 format packets, SO WE CAN "REUSE" THIS RESERVED BIT.
// This DOES mean that no SV2-style devices can be allowed on this loconet.

void codeline_lntcp::code2LN(char *s, int *code, int src, int dst) {
    char data[17];
	data[ 0 ] = codeline_lntcp::OPC_PEER_XFER ;
	data[ 1 ] = 0x10;               // packet length = 16
	data[ 2 ] = (src & 0x7F);       // SRC
	data[ 3 ] = (dst & 0x7F);       // DSTL
	data[ 4 ] = 0x00;               // must be 0x01 - 00=JMP debug

	int pxct = codeline_lntcp::PXCT1_RESERVED;
	if (code[0] & 0x80) pxct |= 0b0001;
	if (code[1] & 0x80) pxct |= 0b0010;
	if (code[2] & 0x80) pxct |= 0b0100;
	if (code[3] & 0x80) pxct |= 0b1000;

	data[ 5 ] =  pxct;    // pxct1
	data[ 6 ] = code[0] & 0x7F;
	data[ 7 ] = code[1] & 0x7F;
	data[ 8 ] = code[2] & 0x7F;
	data[ 9 ] = code[3] & 0x7F;

	pxct = 0x10;
	if (code[4] & 0x80) pxct |= 0b0001;
	if (code[5] & 0x80) pxct |= 0b0010;
	if (code[6] & 0x80) pxct |= 0b0100;
	if (code[7] & 0x80) pxct |= 0b1000;

	data[ 10 ] = pxct;    // pxct2
	data[ 11 ] = code[4] & 0x7F;
	data[ 12 ] = code[5] & 0x7F;
	data[ 13 ] = code[6] & 0x7F;
	data[ 14 ] = code[7] & 0x7F;

    byte checksum = 0xFF;
	for (int i = 0; i < 15; i++) {
      checksum ^= data[i];
    }
    data[ 15 ] = checksum; //checksum

    sprintf(s, "SEND %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
            data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15]);
}

// convenience wrapper arround strtok() - call first time with a string, the rest with NULL
unsigned codeline_lntcp::getValue(char *s) {
    static char buffer4strtok[80];
    char* myCopy;
    if (s) {
        strcpy(buffer4strtok, s);
        myCopy = strtok(buffer4strtok, " ");
    } else {
        myCopy = strtok(NULL, " ");
    }
    return strtoul(myCopy, 0, 16);
}

// Parse a LoconetOverTCP string into components,
// grab 8 data bytes and load into code array
// This is probably better done with sscanf()
int codeline_lntcp::LN2code(char *s, int *code, int *opcode, int *src, int *dst) {
    peerXferMsg pkt;
    *opcode  = getValue(s);

    if (*opcode == codeline_lntcp::OPC_PEER_XFER) {
        pkt.command   = *opcode;
        pkt.mesg_size = getValue(NULL);
        pkt.src       = getValue(NULL);     // source of transfer (0x00-0x7F)
        pkt.dst_l     = getValue(NULL);     // destination  (0x00-0x7F)
        pkt.dst_h     = getValue(NULL);     // must be 0x01
        pkt.pxct1     = getValue(NULL);     //
        pkt.d1        = getValue(NULL);     // data byte 1
        pkt.d2        = getValue(NULL);     // data byte 2
        pkt.d3        = getValue(NULL);     // data byte 3
        pkt.d4        = getValue(NULL);     // data byte 4
        pkt.pxct2     = getValue(NULL);
        pkt.d5        = getValue(NULL);     // data byte 5
        pkt.d6        = getValue(NULL);     // data byte 6
        pkt.d7        = getValue(NULL);     // data byte 7
        pkt.d8        = getValue(NULL);     // data byte 8
        pkt.chksum    = getValue(NULL);     // exclusive-or checksum for the message

        *src = (byte)pkt.src   & 0x7f;
	    *dst = (byte)pkt.dst_l & 0x7f;
        code[0] = (byte)pkt.d1;
        code[1] = (byte)pkt.d2;
        code[2] = (byte)pkt.d3;
        code[3] = (byte)pkt.d4;
        code[4] = (byte)pkt.d5;
        code[5] = (byte)pkt.d6;
        code[6] = (byte)pkt.d7;
        code[7] = (byte)pkt.d8;
        if ((byte)pkt.pxct1 & 0b00000001) code[0] |= 0b10000000;
        if ((byte)pkt.pxct1 & 0b00000010) code[1] |= 0b10000000;
        if ((byte)pkt.pxct1 & 0b00000100) code[2] |= 0b10000000;
        if ((byte)pkt.pxct1 & 0b00001000) code[3] |= 0b10000000;

        if ((byte)pkt.pxct2 & 0b00000001) code[4] |= 0b10000000;
        if ((byte)pkt.pxct2 & 0b00000010) code[5] |= 0b10000000;
        if ((byte)pkt.pxct2 & 0b00000100) code[6] |= 0b10000000;
        if ((byte)pkt.pxct2 & 0b00001000) code[7] |= 0b10000000;

        if (((byte)pkt.pxct1 & PXCT1_RESERVED) == PXCT1_RESERVED) { // If the "don't route" bit is set...
            // SV1 must have the upper nibbles of pxct1 = 0x0x and pxct2 = 0x1x
            // FORCE all packets to look like SV1
            pkt.pxct1 = (pkt.pxct1 & 0X0F) | 0X00;
            pkt.pxct2 = (pkt.pxct2 & 0X0F) | 0X10;
            return SEEN;
        } else {
            return ROUTE;
        }
    }
    return IGNORE;
}

<|endoftext|>


<commit_before>#include <stdlib.h>
#include <Arduino.h>
#include <avr/pgmspace.h>
#include "generator.h"

void g_generator_init(void *_self, g_method method, int32_t period, int32_t phase, int32_t amplitude, int32_t offset)
{
    generator_t *self = (generator_t *)_self;
    self->method = method;
    self->period = period;
    self->phase = phase;
    self->amplitude = amplitude;
    self->offset = offset;
}

void g_sin_init(void *_self, g_method method, int32_t period, int32_t phase, int32_t amplitude, int32_t offset)
{
    generator_t *self = (generator_t *)_self;

    self->period = (int32_t)S_PIM2 * (int32_t)SCALE_FACTOR / period;
    self->phase = -S_PID2 + (S_PIM2 * phase / SCALE_FACTOR);
    self->method = method;
    self->amplitude = amplitude;
    self->offset = offset;
}

void g_square_init(void *_self, g_method method, int32_t period, int32_t phase, int32_t amplitude, int32_t offset, int32_t duty)
{
    square_t *self = (square_t *)_self;
    self->method = method;
    self->period = period;
    self->phase = phase;
    self->amplitude = amplitude;
    self->offset = offset;
    self->duty = duty;
}

int32_t g_sin(void *_self, uint32_t t)
{
    int16_t value;

    generator_t *self = (generator_t *)_self;
    int32_t index = (((int32_t)t * self->period / SCALE_FACTOR + self->phase) % S_PIM2) * NUM_SIN_TABLE_ENTRIES / S_PIM2;
    if (index < 0)
        index = NUM_SIN_TABLE_ENTRIES + index;

    // first explicitly cast to int16_t, to make sure negative numbers are handled correctly
    value = (int16_t)pgm_read_word_near(sin_table + index);
    return (int32_t)value * self->amplitude / SCALE_FACTOR + self->offset;
}

int32_t g_square(void *_self, uint32_t t)
{
    square_t *self = (square_t *)_self;
    int32_t v = ((int32_t)t * SCALE_FACTOR / self->period) + self->phase;
    if (v % SCALE_FACTOR < self->duty)
        return self->amplitude + self->offset;
    else
        return self->offset;
}

int32_t g_sawtooth(void *_self, uint32_t t)
{
    generator_t *self = (generator_t *)_self;

    int32_t v = (((int32_t)t * self->period / SCALE_FACTOR) + self->phase) % SCALE_FACTOR;
    return v * self->amplitude / SCALE_FACTOR + self->offset;
}

int32_t g_step(void *_self, uint32_t t)
{
    generator_t *self = (generator_t *)_self;
    int32_t v = ((int32_t)t * SCALE_FACTOR / self->period) + self->phase;
    if (v >= 0)
        return self->amplitude + self->offset;
    else
        return self->offset;
}

int32_t g_impulse(void *_self, uint32_t t)
{
    generator_t *self = (generator_t *)_self;
    int32_t v = ((int32_t)t * SCALE_FACTOR / self->period) + self->phase;
    if (v >= 0 && v < SCALE_FACTOR)
        return self->amplitude + self->offset;
    else
        return self->offset;
}

int32_t g_line(void *_self, uint32_t t)
{
    generator_t *self = (generator_t *)_self;
    return ((int32_t)t * self->amplitude / SCALE_FACTOR) + self->offset;
}

void g_generator_op_init(void *_self, uint8_t op, generator_t *g, generator_t *g2)
{
    generator_op_t *self = (generator_op_t *)_self;
    self->method = g_generator_op_get;
    self->g = g;
    self->g2 = g2;
    self->op = op;
}

int32_t g_generator_op_get(void *_self, uint32_t t)
{
    generator_op_t *self = (generator_op_t *)_self;
    int32_t         v1, v2;

    v1 = self->g->method(self->g, t);
    v2 = self->g2->method(self->g2, t);

    switch(self->op)
    {
        case OP_ADD:
            return v1 + v2;
        case OP_SUB:
            return v1 - v2;
        case OP_MUL:
            return v1 * v2;
        case OP_DIV:
            return v1 * SCALE_FACTOR / v2;
        case OP_MOD:
            return v1 % v2;
    }
    return 0;
}

void g_abs_init(void *_self, generator_t *g)
{
    g_abs_t *self = (g_abs_t *)_self;
    self->method = g_abs_get;
    self->g = g;
}

int32_t g_abs_get(void *_self, uint32_t t)
{
    generator_op_t *self = (generator_op_t *)_self;
    return abs(self->g->method(self->g, t));
}

void g_constant_init(void *_self, int32_t value)
{
    g_constant_t *self = (g_constant_t *)_self;
    self->value = value;
}

int32_t g_constant_get(void *_self, uint32_t t)
{
    g_constant_t *self = (g_constant_t *)_self;
    return self->value;
}
<commit_msg>Fixed the constant initialization<commit_after>#include <stdlib.h>
#include <Arduino.h>
#include <avr/pgmspace.h>
#include "generator.h"

void g_generator_init(void *_self, g_method method, int32_t period, int32_t phase, int32_t amplitude, int32_t offset)
{
    generator_t *self = (generator_t *)_self;
    self->method = method;
    self->period = period;
    self->phase = phase;
    self->amplitude = amplitude;
    self->offset = offset;
}

void g_sin_init(void *_self, g_method method, int32_t period, int32_t phase, int32_t amplitude, int32_t offset)
{
    generator_t *self = (generator_t *)_self;

    self->period = (int32_t)S_PIM2 * (int32_t)SCALE_FACTOR / period;
    self->phase = -S_PID2 + (S_PIM2 * phase / SCALE_FACTOR);
    self->method = method;
    self->amplitude = amplitude;
    self->offset = offset;
}

void g_square_init(void *_self, g_method method, int32_t period, int32_t phase, int32_t amplitude, int32_t offset, int32_t duty)
{
    square_t *self = (square_t *)_self;
    self->method = method;
    self->period = period;
    self->phase = phase;
    self->amplitude = amplitude;
    self->offset = offset;
    self->duty = duty;
}

int32_t g_sin(void *_self, uint32_t t)
{
    int16_t value;

    generator_t *self = (generator_t *)_self;
    int32_t index = (((int32_t)t * self->period / SCALE_FACTOR + self->phase) % S_PIM2) * NUM_SIN_TABLE_ENTRIES / S_PIM2;
    if (index < 0)
        index += NUM_SIN_TABLE_ENTRIES;

    // first explicitly cast to int16_t, to make sure negative numbers are handled correctly
    value = (int16_t)pgm_read_word_near(sin_table + index);
    return (int32_t)value * self->amplitude / SCALE_FACTOR + self->offset;
}

int32_t g_square(void *_self, uint32_t t)
{
    square_t *self = (square_t *)_self;
    int32_t v = ((int32_t)t * SCALE_FACTOR / self->period) + self->phase;
    if (v % SCALE_FACTOR < self->duty)
        return self->amplitude + self->offset;
    else
        return self->offset;
}

int32_t g_sawtooth(void *_self, uint32_t t)
{
    generator_t *self = (generator_t *)_self;

    int32_t v = (((int32_t)t * self->period / SCALE_FACTOR) + self->phase) % SCALE_FACTOR;
    return v * self->amplitude / SCALE_FACTOR + self->offset;
}

int32_t g_step(void *_self, uint32_t t)
{
    generator_t *self = (generator_t *)_self;
    int32_t v = ((int32_t)t * SCALE_FACTOR / self->period) + self->phase;
    if (v >= 0)
        return self->amplitude + self->offset;
    else
        return self->offset;
}

int32_t g_impulse(void *_self, uint32_t t)
{
    generator_t *self = (generator_t *)_self;
    int32_t v = ((int32_t)t * SCALE_FACTOR / self->period) + self->phase;
    if (v >= 0 && v < SCALE_FACTOR)
        return self->amplitude + self->offset;
    else
        return self->offset;
}

int32_t g_line(void *_self, uint32_t t)
{
    generator_t *self = (generator_t *)_self;
    return ((int32_t)t * self->amplitude / SCALE_FACTOR) + self->offset;
}

void g_generator_op_init(void *_self, uint8_t op, generator_t *g, generator_t *g2)
{
    generator_op_t *self = (generator_op_t *)_self;
    self->method = g_generator_op_get;
    self->g = g;
    self->g2 = g2;
    self->op = op;
}

int32_t g_generator_op_get(void *_self, uint32_t t)
{
    generator_op_t *self = (generator_op_t *)_self;
    int32_t         v1, v2;

    v1 = self->g->method(self->g, t);
    v2 = self->g2->method(self->g2, t);

    switch(self->op)
    {
        case OP_ADD:
            return v1 + v2;
        case OP_SUB:
            return v1 - v2;
        case OP_MUL:
            return v1 * v2;
        case OP_DIV:
            return v1 * SCALE_FACTOR / v2;
        case OP_MOD:
            return v1 % v2;
    }
    return 0;
}

void g_abs_init(void *_self, generator_t *g)
{
    g_abs_t *self = (g_abs_t *)_self;
    self->method = g_abs_get;
    self->g = g;
}

int32_t g_abs_get(void *_self, uint32_t t)
{
    generator_op_t *self = (generator_op_t *)_self;
    return abs(self->g->method(self->g, t));
}

void g_constant_init(void *_self, int32_t value)
{
    g_constant_t *self = (g_constant_t *)_self;
    self->method = g_constant_get;
    self->value = value;
}

int32_t g_constant_get(void *_self, uint32_t t)
{
    g_constant_t *self = (g_constant_t *)_self;
    return self->value;
}
<|endoftext|>


<commit_before>#include "vast/ingestor.h"

#include <ze.h>
#include "vast/exception.h"
#include "vast/event_source.h"
#include "vast/logger.h"
#include "vast/segment.h"
#include "vast/source/broccoli.h"
#include "vast/source/file.h"

namespace vast {

using namespace cppa;

ingestor::ingestor(cppa::actor_ptr tracker,
                   cppa::actor_ptr archive,
                   cppa::actor_ptr index)
  : archive_(archive)
  , index_(index)
{
  LOG(verbose, ingest) << "spawning ingestor @" << id();

  chaining(false);
  init_state = (
      on(atom("initialize"), arg_match) >> [=](size_t max_events_per_chunk,
                                               size_t max_segment_size,
                                               size_t batch_size)
      {
        max_events_per_chunk_ = max_events_per_chunk;
        max_segment_size_ = max_segment_size;
        batch_size_ = batch_size;
      },
      on(atom("ingest"), atom("broccoli"), arg_match) >>
        [=](std::string const& host, unsigned port,
            std::vector<std::string> const& events)
      {
        broccoli_ = spawn<source::broccoli>(tracker, archive_);
        send(broccoli_,
             atom("initialize"),
             max_events_per_chunk_,
             max_segment_size_);

        for (auto& e : events)
          send(broccoli_, atom("subscribe"), e);

        send(broccoli_, atom("bind"), host, port);
      },
      on(atom("ingest"), "bro15conn", arg_match) >> [=](std::string const& file)
      {
        auto source = spawn<source::bro15conn>(self, tracker, file);
        monitor(source);
        sources_.push_back(source);
        send(source, atom("initialize"), max_events_per_chunk_,
             max_segment_size_);
      },
      on(atom("ingest"), "bro2", arg_match) >> [=](std::string const& file)
      {
        auto source = spawn<source::bro2>(self, tracker, file);
        sources_.push_back(source);
        send(source, atom("initialize"), max_events_per_chunk_,
             max_segment_size_);
      },
      on(atom("ingest"), val<std::string>, arg_match) >> [=](std::string const&)
      {
        LOG(error, ingest) << "invalid ingestion file type";
      },
      on(atom("extract")) >> [=]
      {
        for (auto source : sources_)
          send(source, atom("extract"), batch_size_);

        size_t last = 0;
        delayed_send(
            self,
            std::chrono::seconds(2),
            atom("statistics"), atom("print"), last);
      },
      on(atom("statistics"), arg_match) >> [=](size_t rate)
      {
        rates_[last_sender()] = rate;
      },
      on(atom("statistics"), atom("print"), arg_match) >> [=](size_t last)
      {
        size_t sum = 0;
        for (auto& p : rates_)
          sum += p.second;

        if (sum != last)
          LOG(info, ingest)
            << "ingestor @" << id()
            << " ingests at rate " << sum << " events/sec";

        if (! (sources_.empty() && inflight_.empty()))
          delayed_send(
              self,
              std::chrono::seconds(1),
              atom("statistics"), atom("print"), sum);
      },
      on_arg_match >> [=](segment const& s)
      {
        DBG(ingest) << "ingestor @" << id()
          << " relays segment " << s.id()
          << " to archive @" << archive_->id()
          << " and index @" << index_->id();

        index_ << last_dequeued();
        archive_ << last_dequeued();

        assert(inflight_.find(s.id()) == inflight_.end());
        inflight_.emplace(s.id(), 2);

        reply(atom("segment"), atom("ack"), s.id());
      },
      on(atom("segment"), atom("ack"), arg_match) >> [=](ze::uuid const& uuid)
      {
        // Both archive and index send an ack.
        LOG(verbose, ingest)
          << "ingestor @" << id()
          << " received segment ack from @" << last_sender()->id()
          << " for " << uuid;

        auto i = inflight_.find(uuid);
        assert(i != inflight_.end() && i->second > 0);
        if (i->second == 1)
          inflight_.erase(i);
        else
          --i->second;

        if (sources_.empty() && inflight_.empty())
          shutdown();
      },
      on(atom("shutdown")) >> [=]
      {
        if (broccoli_)
          broccoli_ << last_dequeued();
        if (sources_.empty() && inflight_.empty())
          shutdown();
        for (auto source : sources_)
          source << last_dequeued();
      },
      on(atom("DOWN"), arg_match) >> [=](uint32_t reason)
      {
        auto i = std::find(sources_.begin(), sources_.end(), last_sender());
        assert(i != sources_.end());
        sources_.erase(i);

        if (sources_.empty() && inflight_.empty())
          shutdown();
      });
}

void ingestor::shutdown()
{
  quit();
  LOG(verbose, ingest) << "ingestor @" << id() << " terminated";
}

} // namespace vast
<commit_msg>Fix leak.<commit_after>#include "vast/ingestor.h"

#include <ze.h>
#include "vast/exception.h"
#include "vast/event_source.h"
#include "vast/logger.h"
#include "vast/segment.h"
#include "vast/source/broccoli.h"
#include "vast/source/file.h"

namespace vast {

using namespace cppa;

ingestor::ingestor(cppa::actor_ptr tracker,
                   cppa::actor_ptr archive,
                   cppa::actor_ptr index)
  : archive_(archive)
  , index_(index)
{
  LOG(verbose, ingest) << "spawning ingestor @" << id();

  chaining(false);
  init_state = (
      on(atom("initialize"), arg_match) >> [=](size_t max_events_per_chunk,
                                               size_t max_segment_size,
                                               size_t batch_size)
      {
        max_events_per_chunk_ = max_events_per_chunk;
        max_segment_size_ = max_segment_size;
        batch_size_ = batch_size;
      },
      on(atom("ingest"), atom("broccoli"), arg_match) >>
        [=](std::string const& host, unsigned port,
            std::vector<std::string> const& events)
      {
        broccoli_ = spawn<source::broccoli>(tracker, archive_);
        send(broccoli_,
             atom("initialize"),
             max_events_per_chunk_,
             max_segment_size_);

        for (auto& e : events)
          send(broccoli_, atom("subscribe"), e);

        send(broccoli_, atom("bind"), host, port);
      },
      on(atom("ingest"), "bro15conn", arg_match) >> [=](std::string const& file)
      {
        auto source = spawn<source::bro15conn>(self, tracker, file);
        monitor(source);
        sources_.push_back(source);
        send(source, atom("initialize"), max_events_per_chunk_,
             max_segment_size_);
      },
      on(atom("ingest"), "bro2", arg_match) >> [=](std::string const& file)
      {
        auto source = spawn<source::bro2>(self, tracker, file);
        sources_.push_back(source);
        send(source, atom("initialize"), max_events_per_chunk_,
             max_segment_size_);
      },
      on(atom("ingest"), val<std::string>, arg_match) >> [=](std::string const&)
      {
        LOG(error, ingest) << "invalid ingestion file type";
      },
      on(atom("extract")) >> [=]
      {
        for (auto source : sources_)
          send(source, atom("extract"), batch_size_);

        size_t last = 0;
        delayed_send(
            self,
            std::chrono::seconds(2),
            atom("statistics"), atom("print"), last);
      },
      on(atom("statistics"), arg_match) >> [=](size_t rate)
      {
        rates_[last_sender()] = rate;
      },
      on(atom("statistics"), atom("print"), arg_match) >> [=](size_t last)
      {
        size_t sum = 0;
        for (auto& p : rates_)
          sum += p.second;

        if (sum != last)
          LOG(info, ingest)
            << "ingestor @" << id()
            << " ingests at rate " << sum << " events/sec";

        if (! (sources_.empty() && inflight_.empty()))
          delayed_send(
              self,
              std::chrono::seconds(1),
              atom("statistics"), atom("print"), sum);
      },
      on_arg_match >> [=](segment const& s)
      {
        DBG(ingest) << "ingestor @" << id()
          << " relays segment " << s.id()
          << " to archive @" << archive_->id()
          << " and index @" << index_->id();

        index_ << last_dequeued();
        archive_ << last_dequeued();

        assert(inflight_.find(s.id()) == inflight_.end());
        inflight_.emplace(s.id(), 2);

        reply(atom("segment"), atom("ack"), s.id());
      },
      on(atom("segment"), atom("ack"), arg_match) >> [=](ze::uuid const& uuid)
      {
        // Both archive and index send an ack.
        LOG(verbose, ingest)
          << "ingestor @" << id()
          << " received segment ack from @" << last_sender()->id()
          << " for " << uuid;

        auto i = inflight_.find(uuid);
        assert(i != inflight_.end() && i->second > 0);
        if (i->second == 1)
          inflight_.erase(i);
        else
          --i->second;

        if (sources_.empty() && inflight_.empty())
          shutdown();
      },
      on(atom("shutdown")) >> [=]
      {
        if (broccoli_)
          broccoli_ << last_dequeued();
        if (sources_.empty() && inflight_.empty())
          shutdown();
        for (auto source : sources_)
          source << last_dequeued();
      },
      on(atom("DOWN"), arg_match) >> [=](uint32_t reason)
      {
        auto i = std::find(sources_.begin(), sources_.end(), last_sender());
        assert(i != sources_.end());
        sources_.erase(i);

        auto j = rates_.find(last_sender());
        if (j != rates_.end());
          rates_.erase(j);

        if (sources_.empty() && inflight_.empty())
          shutdown();
      });
}

void ingestor::shutdown()
{
  quit();
  LOG(verbose, ingest) << "ingestor @" << id() << " terminated";
}

} // namespace vast
<|endoftext|>


<commit_before>#include <node.h>
#include <uv.h>
#include <string>
#include "tree_sitter/runtime.h"
#include "nan.h"

using namespace v8;

namespace node_tree_sitter_cli {

static Nan::Persistent<Function> constructor;

NAN_METHOD(LoadLanguage) {
  Handle<String> js_lib_file_name = Handle<String>::Cast(info[0]);
  Handle<String> js_language_function_name = Handle<String>::Cast(info[1]);
  std::string language_function_name(*String::Utf8Value(js_language_function_name));
  std::string lib_file_name(*String::Utf8Value(js_lib_file_name));

  uv_lib_t parser_lib;
  int error_code = uv_dlopen(lib_file_name.c_str(), &parser_lib);
  if (error_code) {
    std::string message(uv_dlerror(&parser_lib));
    Nan::ThrowError(("Couldn't open language file - " + message).c_str());
    return;
  }

  const TSLanguage * (* language_fn)() = NULL;
  error_code = uv_dlsym(&parser_lib, language_function_name.c_str(), (void **)&language_fn);
  if (error_code) {
    std::string message(uv_dlerror(&parser_lib));
    Nan::ThrowError(("Couldn't load language function - " + message).c_str());
    return;
  }

  if (!language_fn) {
    Nan::ThrowError("Could not load language");
    return;
  }

  Local<Object> instance = Nan::New(constructor)->NewInstance();
  Nan::SetInternalFieldPointer(instance, 0, (void *)language_fn());
  info.GetReturnValue().Set(instance);
}

NAN_METHOD(NewLanguage) {
  info.GetReturnValue().Set(Nan::Null());
}

void InitLanguage(v8::Handle<v8::Object> exports) {
  Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(NewLanguage);
  tpl->SetClassName(Nan::New("DynamicallyLoadedLanguage").ToLocalChecked());
  tpl->InstanceTemplate()->SetInternalFieldCount(1);
  constructor.Reset(tpl->GetFunction());
}

}  // namespace node_tree_sitter_cli
<commit_msg>Fix build warning w/ newer v8 versions<commit_after>#include <node.h>
#include <uv.h>
#include <string>
#include "tree_sitter/runtime.h"
#include "nan.h"

using namespace v8;

namespace node_tree_sitter_cli {

static Nan::Persistent<Function> constructor;

NAN_METHOD(LoadLanguage) {
  Handle<String> js_lib_file_name = Handle<String>::Cast(info[0]);
  Handle<String> js_language_function_name = Handle<String>::Cast(info[1]);
  std::string language_function_name(*String::Utf8Value(js_language_function_name));
  std::string lib_file_name(*String::Utf8Value(js_lib_file_name));

  uv_lib_t parser_lib;
  int error_code = uv_dlopen(lib_file_name.c_str(), &parser_lib);
  if (error_code) {
    std::string message(uv_dlerror(&parser_lib));
    Nan::ThrowError(("Couldn't open language file - " + message).c_str());
    return;
  }

  const TSLanguage * (* language_fn)() = NULL;
  error_code = uv_dlsym(&parser_lib, language_function_name.c_str(), (void **)&language_fn);
  if (error_code) {
    std::string message(uv_dlerror(&parser_lib));
    Nan::ThrowError(("Couldn't load language function - " + message).c_str());
    return;
  }

  if (!language_fn) {
    Nan::ThrowError("Could not load language");
    return;
  }

  Local<Object> instance = Nan::New(constructor)->NewInstance(Nan::GetCurrentContext()).ToLocalChecked();
  Nan::SetInternalFieldPointer(instance, 0, (void *)language_fn());
  info.GetReturnValue().Set(instance);
}

NAN_METHOD(NewLanguage) {
  info.GetReturnValue().Set(Nan::Null());
}

void InitLanguage(v8::Handle<v8::Object> exports) {
  Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(NewLanguage);
  tpl->SetClassName(Nan::New("DynamicallyLoadedLanguage").ToLocalChecked());
  tpl->InstanceTemplate()->SetInternalFieldCount(1);
  constructor.Reset(tpl->GetFunction());
}

}  // namespace node_tree_sitter_cli
<|endoftext|>