<commit_before>#ifndef SN_ALGDS_HEAP_H
#define SN_ALGDS_HEAP_H

#include <bits/stdc++.cpp>
using namespace std;

namespace heap {
    // left-child right sibling
    template <typename T>
    class LCRSBinaryTreeNode {
        LCRSBinaryTreeNode* m_parent = nullptr;
        LCRSBinaryTreeNode* m_prev = nullptr;
        LCRSBinaryTreeNode* m_left = nullptr; // child
        LCRSBinaryTreeNode* m_right = nullptr; // sibling;
        T m_value = T{};
    public:
        LCRSBinaryTreeNode() noexcept {}
        LCRSBinaryTreeNode(const T& v) noexcept : m_value{v} {}
        LCRSBinaryTreeNode(T&& v) noexcept : m_value{std::move(v)} {}

        LCRSBinaryTreeNode*& left_child() noexcept {
            return m_left;
        }

        LCRSBinaryTreeNode*& right_child() noexcept {
            return m_left->sibling();
        }

        LCRSBinaryTreeNode*& kth_child(size_t k) noexcept {
            TreeNode* res = m_left;
            while (k != 0 && res != nullptr) {
                res = res->sibling();
                --k;
            }
            return res;
        }

        LCRSBinaryTreeNode*& sibling() noexcept {
            return m_right;
        }

        LCRSBinaryTreeNode*& previous() noexcept {
            return m_prev;
        }

        LCRSBinaryTreeNode*& parent() noexcept {
            return m_parent;
        }

        T& value() noexcept {
            return m_value;
        }

        const T& value() noexcept {
            return m_value;
        }

    };

    template <typename T>
    struct MinPolicy {
        static bool compare(const T& l, const T& r) noexcept {
            return l < r;
        }
    };

    template <typename T>
    struct MaxPolicy {
        static bool compare(const T& l, const T& r) noexcept {
            return l > r;
        }
    };

    template <typename T, typename TN = LCRSBinaryTreeNode<T>, typename ComparePolicy = MinPolicy<T>>
    class BinaryHeap {
        TN* m_root = nullptr;
        TN* m_end = nullptr;
    public:
        BinaryHeap() {
            m_root = new TN;
            m_end = m_root;
        }

        void insert(const T& v) {
            TN* new_node = new TN{v};
            if (m_end->sibling() == nullptr) {
                m_end->sibling() = new_node;
                new_node->parent() = m_end->parent();
            } else {
                m_end->left_child() = new_node;
                new_node->parent() = m_end;
                m_end = ComparePolicy::compare(new_node->parent()->value(), new_node->value()) ? m_end : new_node ;
            }
            TN* n = new_node;
            TN* p = n->parent();
            while (p != nullptr && ComparePolicy::compare(p->value(), n->value())) {
                std::swap(p->value(), n->value());
                n = p;
                p = n->parent();
            }
        }

        // Only apply to !ComparePoly::compare(node->value(), v)
        void update(TN* node, const T& v) {
            node->value() = v;
            short sign = 0;
            if (node->left_child() != nullptr && ComparePolicy::compare(node->left_child()->value(), v)) {
                sign = 1;
            }
            if (node->right_child() != nullptr && ComparePolicy::compare(node->right_child()->value(), v)) {
                sign = 2;
            }
            if (sign == 0) return;
            if (sign == 1) {
                std::swap(node->value(), node->left_child->value());
                update(node->left_child(), v);
            } else {
                std::swap(node->value(), node->right_child->value());
                update(node->right_child(), v);
            }
        }

        T remove() {
            T res = m_root->left_child()->value();
            T upd;
            if (m_end->sibling() != nullptr) {
                upd = m_end->sibling()->value();
                delete m_end->sibling();
            } else {
                upd = m_end->value();
                m_end = m_end->parent();
                delete m_end->left_child();
            }
            update(m_root->left_child(), upd);
            return res;
        }

        void destroy(TN* node) {
            if (node == nullptr) return;
            if (node->left_child() != nullptr)
                destroy(node->left_child());
            if (node->right_child() != nullptr)
                destroy(node->right_child());
            delete node;
        }

        ~BinaryHeap() {
            destroy(m_root);
        }
    };

    template <typename T, typename TN = LCRSBinaryTreeNode<T>, typename ComparePolicy = MinPolicy<T>>
    class PairingHeap {
        TN* m_root = nullptr;
        size_t m_sz = 0;
    public:
        PairingHeap() : m_root{new TN} {}

        PairingHeap(const T& v) : m_root{new TN{v}} {}

        bool is_empty() noexcept {
            return m_sz == 0;
        }

        size_t size() noexcept {
            return m_sz;
        }

        T top() noexcept {
            return m_root->value();
        }

        void merge(TN* other_root) noexcept {
            T max = top();
            if (ComparePolicy::compare(max, other_root->top())) {
                TN* rest = m_root->left_child();
                other_root->sibling() = rest;
                m_root->left_child() = other_root;
            } else {
                TN* rest = other_root->left_child();
                m_root->sibling() = rest;
                other_root->left_child() = m_root;
                m_root = other_root;
            }
        }

        TN* merge(TN* root, TN* other_root) noexcept {
            T max = root->top();
            if (ComparePolicy::compare(max, other_root->top())) {
                TN* rest = root->left_child();
                other_root->sibling() = rest;
                root->left_child() = other_root;
            } else {
                TN* rest = other_root->left_child();
                root->sibling() = rest;
                other_root->left_child() = root;
                root = other_root;
            }
            return root;
        }

        void insert(const T& v) {
            TN* new_heap = new TN{v};
            merge(new_heap);
        }

        // If we have parent -> we can directly change parent left_child
        void update(TN* node, const T& v) {
            TN* new_heap = new TN{v};
            new_heap->left_child() = node->left_child();

            TN* new_left = node->sibling();
            // A copy
            node->value() = new_left->value();
            node->sibling() = new_left->sibling();
            node->left_child() = new_left->left_child();

            delete new_left;
            merge(new_heap);
        }

        T pop() {
            std::list<TN*> ns;
            TN* cur = m_root->left_child();
            while (cur != nullptr) {
                ns.push_back(cur);
                cur = cur->sibling();
            }
            T res = m_root->value();
            delete m_root;
            std::list<TN*> nns;
            while (ns.size() >= 2) {
                TN* tn1 = ns.pop_front();
                TN* tn2 = ns.pop_front();
                nns.push_back(merge(tn1, tn2));
            }
            if (ns.size() == 1)
                nns.push_back(ns.pop_front());
            while (nns.size() != 1) {
                TN* tn1 = nns.pop_back();
                TN* tn2 = nns.pop_back();
                nns.push_back(merge(tn1, tn2));
            }
            m_root = nns.pop_back();
            return res;
        }

        TN* pop(TN* root) {
            std::list<TN*> ns;
            TN* cur = root->left_child();
            while (cur != nullptr) {
                ns.push_back(cur);
                cur = cur->sibling();
            }
            T res = root->value();
            delete m_root;
            std::list<TN*> nns;
            while (ns.size() >= 2) {
                TN* tn1 = ns.pop_front();
                TN* tn2 = ns.pop_front();
                nns.push_back(merge(tn1, tn2));
            }
            if (ns.size() == 1)
                nns.push_back(ns.pop_front());
            while (nns.size() != 1) {
                TN* tn1 = nns.pop_back();
                TN* tn2 = nns.pop_back();
                nns.push_back(merge(tn1, tn2));
            }
            return nns.pop_back();
        }

        T remove(TN* node) {
            if (node == m_root) {
                return pop();
            } else {
                TN* new_heap = new TN{node->value()};
                new_heap->left_child() = node->left_child();

                TN* new_left = node->sibling();
                // A copy
                node->value() = new_left->value();
                node->sibling() = new_left->sibling();
                node->left_child() = new_left->left_child();

                delete new_left;

                TN* adjusted_new_heap = pop(new_heap);
                merge(adjusted_new_heap);
            }
        }

        void destroy(TN* node) {
            if (node == nullptr) return;
            if (node->left_child() != nullptr)
                destroy(node->left_child());
            if (node->sibling() != nullptr)
                destroy(node->sibling());
            delete node;
        }

        ~PairingHeap() {
            destroy(m_root);
        }
    };
}

#endif<commit_msg>Add make_heap<commit_after>#ifndef SN_ALGDS_HEAP_H
#define SN_ALGDS_HEAP_H

#include <bits/stdc++.cpp>
using namespace std;

namespace heap {
    // left-child right sibling
    template <typename T>
    class LCRSBinaryTreeNode {
        LCRSBinaryTreeNode* m_parent = nullptr;
        LCRSBinaryTreeNode* m_prev = nullptr;
        LCRSBinaryTreeNode* m_left = nullptr; // child
        LCRSBinaryTreeNode* m_right = nullptr; // sibling;
        T m_value = T{};
    public:
        LCRSBinaryTreeNode() noexcept {}
        LCRSBinaryTreeNode(const T& v) noexcept : m_value{v} {}
        LCRSBinaryTreeNode(T&& v) noexcept : m_value{std::move(v)} {}

        LCRSBinaryTreeNode*& left_child() noexcept {
            return m_left;
        }

        LCRSBinaryTreeNode*& right_child() noexcept {
            return m_left->sibling();
        }

        LCRSBinaryTreeNode*& kth_child(size_t k) noexcept {
            TreeNode* res = m_left;
            while (k != 0 && res != nullptr) {
                res = res->sibling();
                --k;
            }
            return res;
        }

        LCRSBinaryTreeNode*& sibling() noexcept {
            return m_right;
        }

        LCRSBinaryTreeNode*& previous() noexcept {
            return m_prev;
        }

        LCRSBinaryTreeNode*& parent() noexcept {
            return m_parent;
        }

        T& value() noexcept {
            return m_value;
        }

        const T& value() noexcept {
            return m_value;
        }

    };

    template <typename T>
    struct MinPolicy {
        static bool compare(const T& l, const T& r) noexcept {
            return l < r;
        }
    };

    template <typename T>
    struct MaxPolicy {
        static bool compare(const T& l, const T& r) noexcept {
            return l > r;
        }
    };

    template <typename T, typename TN = LCRSBinaryTreeNode<T>, typename ComparePolicy = MinPolicy<T>>
    class BinaryHeap {
        TN* m_root = nullptr;
        TN* m_end = nullptr;
    public:
        BinaryHeap() {
            m_root = new TN;
            m_end = m_root;
        }

        void insert(const T& v) {
            TN* new_node = new TN{v};
            if (m_end->sibling() == nullptr) {
                m_end->sibling() = new_node;
                new_node->parent() = m_end->parent();
            } else {
                m_end->left_child() = new_node;
                new_node->parent() = m_end;
                m_end = ComparePolicy::compare(new_node->parent()->value(), new_node->value()) ? m_end : new_node ;
            }
            TN* n = new_node;
            TN* p = n->parent();
            while (p != nullptr && ComparePolicy::compare(p->value(), n->value())) {
                std::swap(p->value(), n->value());
                n = p;
                p = n->parent();
            }
        }

        // Only apply to !ComparePoly::compare(node->value(), v)
        void update(TN* node, const T& v) {
            node->value() = v;
            short sign = 0;
            if (node->left_child() != nullptr && ComparePolicy::compare(node->left_child()->value(), v)) {
                sign = 1;
            }
            if (node->right_child() != nullptr && ComparePolicy::compare(node->right_child()->value(), v)) {
                sign = 2;
            }
            if (sign == 0) return;
            if (sign == 1) {
                std::swap(node->value(), node->left_child->value());
                update(node->left_child(), v);
            } else {
                std::swap(node->value(), node->right_child->value());
                update(node->right_child(), v);
            }
        }

        T remove() {
            T res = m_root->left_child()->value();
            T upd;
            if (m_end->sibling() != nullptr) {
                upd = m_end->sibling()->value();
                delete m_end->sibling();
            } else {
                upd = m_end->value();
                m_end = m_end->parent();
                delete m_end->left_child();
            }
            update(m_root->left_child(), upd);
            return res;
        }

        void destroy(TN* node) {
            if (node == nullptr) return;
            if (node->left_child() != nullptr)
                destroy(node->left_child());
            if (node->right_child() != nullptr)
                destroy(node->right_child());
            delete node;
        }

        ~BinaryHeap() {
            destroy(m_root);
        }
    };

    template <typename T, typename TN = LCRSBinaryTreeNode<T>, typename ComparePolicy = MinPolicy<T>>
    class PairingHeap {
        TN* m_root = nullptr;
        size_t m_sz = 0;
    public:
        PairingHeap() : m_root{new TN} {}

        PairingHeap(const T& v) : m_root{new TN{v}} {}

        bool is_empty() noexcept {
            return m_sz == 0;
        }

        size_t size() noexcept {
            return m_sz;
        }

        T top() noexcept {
            return m_root->value();
        }

        void merge(TN* other_root) noexcept {
            T max = top();
            if (ComparePolicy::compare(max, other_root->top())) {
                TN* rest = m_root->left_child();
                other_root->sibling() = rest;
                m_root->left_child() = other_root;
            } else {
                TN* rest = other_root->left_child();
                m_root->sibling() = rest;
                other_root->left_child() = m_root;
                m_root = other_root;
            }
        }

        TN* merge(TN* root, TN* other_root) noexcept {
            T max = root->top();
            if (ComparePolicy::compare(max, other_root->top())) {
                TN* rest = root->left_child();
                other_root->sibling() = rest;
                root->left_child() = other_root;
            } else {
                TN* rest = other_root->left_child();
                root->sibling() = rest;
                other_root->left_child() = root;
                root = other_root;
            }
            return root;
        }

        void insert(const T& v) {
            TN* new_heap = new TN{v};
            merge(new_heap);
        }

        // If we have parent -> we can directly change parent left_child
        void update(TN* node, const T& v) {
            TN* new_heap = new TN{v};
            new_heap->left_child() = node->left_child();

            TN* new_left = node->sibling();
            // A copy
            node->value() = new_left->value();
            node->sibling() = new_left->sibling();
            node->left_child() = new_left->left_child();

            delete new_left;
            merge(new_heap);
        }

        T pop() {
            std::list<TN*> ns;
            TN* cur = m_root->left_child();
            while (cur != nullptr) {
                ns.push_back(cur);
                cur = cur->sibling();
            }
            T res = m_root->value();
            delete m_root;
            std::list<TN*> nns;
            while (ns.size() >= 2) {
                TN* tn1 = ns.pop_front();
                TN* tn2 = ns.pop_front();
                nns.push_back(merge(tn1, tn2));
            }
            if (ns.size() == 1)
                nns.push_back(ns.pop_front());
            while (nns.size() != 1) {
                TN* tn1 = nns.pop_back();
                TN* tn2 = nns.pop_back();
                nns.push_back(merge(tn1, tn2));
            }
            m_root = nns.pop_back();
            return res;
        }

        TN* pop(TN* root) {
            std::list<TN*> ns;
            TN* cur = root->left_child();
            while (cur != nullptr) {
                ns.push_back(cur);
                cur = cur->sibling();
            }
            T res = root->value();
            delete m_root;
            std::list<TN*> nns;
            while (ns.size() >= 2) {
                TN* tn1 = ns.pop_front();
                TN* tn2 = ns.pop_front();
                nns.push_back(merge(tn1, tn2));
            }
            if (ns.size() == 1)
                nns.push_back(ns.pop_front());
            while (nns.size() != 1) {
                TN* tn1 = nns.pop_back();
                TN* tn2 = nns.pop_back();
                nns.push_back(merge(tn1, tn2));
            }
            return nns.pop_back();
        }

        T remove(TN* node) {
            if (node == m_root) {
                return pop();
            } else {
                TN* new_heap = new TN{node->value()};
                new_heap->left_child() = node->left_child();

                TN* new_left = node->sibling();
                // A copy
                node->value() = new_left->value();
                node->sibling() = new_left->sibling();
                node->left_child() = new_left->left_child();

                delete new_left;

                TN* adjusted_new_heap = pop(new_heap);
                merge(adjusted_new_heap);
            }
        }

        void destroy(TN* node) {
            if (node == nullptr) return;
            if (node->left_child() != nullptr)
                destroy(node->left_child());
            if (node->sibling() != nullptr)
                destroy(node->sibling());
            delete node;
        }

        ~PairingHeap() {
            destroy(m_root);
        }
    };

    // Max-heap
    void adjust_heap(int arr[], size_t sz, size_t parent) {
        size_t left = idx * 2;
        size_t right = idx * 2 + 1;
        size_t large = parent;
        while (left < sz || right <sz) {
            if (left < sz && arr[parent] < arr[left]) {
                large = left;
            }
            if (right < sz && arr[parent] < arr[right]) {
                large = right;
            }
            if (large != parent) {
                std::swap(arr[parent], arr[large]);
                parent = large;
                left = parent * 2;
                right = parent * 2 + 1;
            } else {
                break;
            }
        }
    }

    void make_heap(int arr[], size_t sz) {
        size_t last_non_leaf = sz / 2 - 1;
        for (size_t i = last_non_leaf; i >=0; --i) {
            adjust_heap(arr, sz, i);
        }
    }
}

#endif<|endoftext|>


<commit_before>#pragma once
#include <cstdint>
#include <array>
#include <vector>
#include <functional>
#include "vm/utils.hpp"

namespace yagbe
{
	class palette_entry
	{
	public:
		palette_entry(uint8_t entry) : _entry(entry)
		{

		}

		uint8_t color_index(int i) const
		{
			return (_entry >> i*2) & 0b11;
		}

		yagbe::color color(int i) const
		{
			return colors()[color_index(i)];
		}

		constexpr static std::array<yagbe::color, 4> black_white_colors()
		{
			return std::array<yagbe::color, 4>{
				yagbe::color{ 250,250,250,255 },
				yagbe::color{ 116,116,116,255 },
				yagbe::color{ 188,188,188,255 },
				yagbe::color{ 0,0,0,255 },
			};
		}

		constexpr static std::array<yagbe::color, 4> lcd_colors()
		{
			return std::array<yagbe::color, 4>{
				yagbe::color{ 252,232,140,255 },
				yagbe::color{ 220,180,92,255 },
				yagbe::color{ 152,124,60,255 },
				yagbe::color{ 76,60,28,255 },
			};
		}

		constexpr static std::array<yagbe::color, 4> colors()
		{
			return lcd_colors();
		}
	protected:
		uint8_t _entry;
	};

};<commit_msg>drafting palette<commit_after>#pragma once
#include <cstdint>
#include <array>
#include <vector>
#include <functional>
#include "vm/utils.hpp"

namespace yagbe
{
	class palette_entry
	{
	public:
		palette_entry(uint8_t entry) : _entry(entry)
		{

		}

		uint8_t color_index(int i) const
		{
			return (_entry >> i*2) & 0b11;
		}

		yagbe::color color(int i) const
		{
			return colors()[color_index(i)];
		}

		constexpr static std::array<yagbe::color, 4> black_white_colors()
		{
			return std::array<yagbe::color, 4>{
				yagbe::color{ 250,250,250,255 },
				yagbe::color{ 116,116,116,255 },
				yagbe::color{ 188,188,188,255 },
				yagbe::color{ 0,0,0,255 },
			};
		}

		constexpr static std::array<yagbe::color, 4> lcd_colors()
		{
			return std::array<yagbe::color, 4>{
				yagbe::color{ 252,232,140,255 },
				yagbe::color{ 220,180,92,255 },
				yagbe::color{ 152,124,60,255 },
				yagbe::color{ 76,60,28,255 },
			};
		}

		constexpr static std::array<yagbe::color, 4> colors()
		{
			return lcd_colors();
		}
	protected:
		uint8_t _entry;
	};

	class cgb_specific_palette
	{
		struct entry
		{
			std::array<yagbe::color, 3> color;
		};

	};

	class palette
	{
	public:

	};

};<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

//-------------------------------------------------------------------------
//     AOD class to store calorimeter cell data
//     Author: Markus Oldenburg, CERN
//-------------------------------------------------------------------------

#include "AliAODCaloCells.h"

ClassImp(AliAODCaloCells)

AliAODCaloCells::AliAODCaloCells() : AliVCaloCells(), fNCells(0), fCellNumber(0), fAmplitude(0), fIsSorted(kTRUE), fType(kUndef)
{
  // default constructor
}

AliAODCaloCells::AliAODCaloCells(const char* name, const char* title, VCells_t ttype) :
    AliVCaloCells(name, title), fNCells(0), fCellNumber(0), fAmplitude(0), fIsSorted(kTRUE), fType(ttype)
{
  //constructor
}

AliAODCaloCells::AliAODCaloCells(const AliAODCaloCells& cells) :
    AliVCaloCells(cells),
    fNCells(cells.fNCells),
    fCellNumber(0),
    fAmplitude(0),
    fIsSorted(cells.fIsSorted),
    fType(cells.fType)
{
// Copy constructor
  fCellNumber = new Short_t[fNCells];
  fAmplitude  = new Double32_t[fNCells];

  for (Int_t i = 0; i < fNCells; i++) {
    fCellNumber[i]    = cells.fCellNumber[i];
    fAmplitude[i]     = cells.fAmplitude[i];
  }
}

AliAODCaloCells& AliAODCaloCells::operator=(const AliAODCaloCells& cells)
{
    // Assignment operator
  if(&cells == this) return *this;
  fNCells = cells.fNCells;
  for (Int_t i = 0; i < fNCells; i++) {
    fCellNumber[i]    = cells.fCellNumber[i];
    fAmplitude[i]     = cells.fAmplitude[i];
  }
  SetName(cells.GetName()) ;
  SetTitle(cells.GetTitle()) ;
  return *this;
}

AliAODCaloCells::~AliAODCaloCells()
{
  // destructor

  DeleteContainer();
}

void AliAODCaloCells::Clear(const Option_t*)
{
  // clear

  DeleteContainer();
}

void AliAODCaloCells::Copy(TObject &obj) const {

  // this overwrites the virtual TOBject::Copy()
  // to allow run time copying without casting
  // in AliESDEvent

  if(this==&obj)return;
  AliAODCaloCells *robj = dynamic_cast<AliAODCaloCells*>(&obj);
  if(!robj)return; // not an AliAODCaloCells
  *robj = *this;

}

AliVCaloCells *AliAODCaloCells::CopyCaloCells(Bool_t all = kTRUE) const {

  // copy the calo cells into a new object. If option all=FALSE, just the object type,
  // for mixing

  AliVCaloCells *obj =  new AliAODCaloCells();

  if(all){
    obj->SetName (GetName()) ;
    obj->SetTitle(GetTitle()) ;
    obj->SetType (GetType()) ;

    obj->SetNumberOfCells(fNCells);
    for (Short_t i = 0; i < fNCells; i++)
      obj->SetCell(i,fCellNumber[i],fAmplitude[i],-1);
  }

  return obj;

}

void AliAODCaloCells::CreateContainer(Short_t nCells)
{
  // function that creates container to store calorimeter cell data

  DeleteContainer();

  if (nCells <= 0) {
    fNCells = 0;
    return;
  }

  fNCells = nCells;

  fCellNumber = new Short_t[fNCells];
  fAmplitude  = new Double32_t[fNCells];

  // set to zero
  for(int i = 0;i<fNCells;++i){
    fAmplitude[i] = fCellNumber[i] = 0 ;
  }
}

void AliAODCaloCells::DeleteContainer()
{
  // deletes allocated memory

  if (fCellNumber)
  {
    delete[] fCellNumber;
    fCellNumber = NULL;
  }

  if (fAmplitude)
  {
    delete[] fAmplitude;
    fAmplitude = NULL;
  }

  fNCells = 0;
  fIsSorted = kFALSE;
}

void AliAODCaloCells::Sort()
{
  // sort the cell array by cell number

  Int_t *idxArray = new Int_t[fNCells];
  TMath::Sort(fNCells,fCellNumber,idxArray,kFALSE);

  Short_t    *newIndex     = new Short_t[fNCells];
  Double32_t *newAmplitude = new Double32_t[fNCells];
  for (Int_t i=0; i < fNCells; i++) {
    newIndex[i]     = fCellNumber[idxArray[i]];
    newAmplitude[i] = fAmplitude[idxArray[i]];
  }
  delete [] fCellNumber;
  delete [] fAmplitude;
  fCellNumber = newIndex;
  fAmplitude  = newAmplitude;

  delete [] idxArray;

  fIsSorted = kTRUE;
}

Bool_t AliAODCaloCells::SetCell(Short_t pos, Short_t cellNumber, Double32_t amplitude, Double32_t /*time*/)
{
  // Sets a cell at the given position

  if (pos>=0 && pos < fNCells) {
    fCellNumber[pos] = cellNumber;
    fAmplitude[pos]  = amplitude;
    fIsSorted = kFALSE;
    return kTRUE;
  } else {
    return kFALSE;
  }
}
<commit_msg>Bug fix in assignment operator. C. Loizides<commit_after>/**************************************************************************
 * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

//-------------------------------------------------------------------------
//     AOD class to store calorimeter cell data
//     Author: Markus Oldenburg, CERN
//-------------------------------------------------------------------------

#include "AliAODCaloCells.h"

ClassImp(AliAODCaloCells)

AliAODCaloCells::AliAODCaloCells() : AliVCaloCells(), fNCells(0), fCellNumber(0), fAmplitude(0), fIsSorted(kTRUE), fType(kUndef)
{
  // default constructor
}

AliAODCaloCells::AliAODCaloCells(const char* name, const char* title, VCells_t ttype) :
    AliVCaloCells(name, title), fNCells(0), fCellNumber(0), fAmplitude(0), fIsSorted(kTRUE), fType(ttype)
{
  //constructor
}

AliAODCaloCells::AliAODCaloCells(const AliAODCaloCells& cells) :
    AliVCaloCells(cells),
    fNCells(cells.fNCells),
    fCellNumber(0),
    fAmplitude(0),
    fIsSorted(cells.fIsSorted),
    fType(cells.fType)
{
// Copy constructor
  fCellNumber = new Short_t[fNCells];
  fAmplitude  = new Double32_t[fNCells];

  for (Int_t i = 0; i < fNCells; i++) {
    fCellNumber[i]    = cells.fCellNumber[i];
    fAmplitude[i]     = cells.fAmplitude[i];
  }
}

AliAODCaloCells& AliAODCaloCells::operator=(const AliAODCaloCells& cells)
{
    // Assignment operator
  if(&cells == this) return *this;
  delete [] fCellNumber;
  delete [] fAmplitude;

  fNCells = cells.fNCells;

  fCellNumber = new Short_t[fNCells];
  fAmplitude  = new Double32_t[fNCells];

  for (Int_t i = 0; i < fNCells; i++) {
    fCellNumber[i]    = cells.fCellNumber[i];
    fAmplitude[i]     = cells.fAmplitude[i];
  }
  SetName(cells.GetName()) ;
  SetTitle(cells.GetTitle()) ;
  return *this;
}

AliAODCaloCells::~AliAODCaloCells()
{
  // destructor

  DeleteContainer();
}

void AliAODCaloCells::Clear(const Option_t*)
{
  // clear

  DeleteContainer();
}

void AliAODCaloCells::Copy(TObject &obj) const {

  // this overwrites the virtual TOBject::Copy()
  // to allow run time copying without casting
  // in AliESDEvent

  if(this==&obj)return;
  AliAODCaloCells *robj = dynamic_cast<AliAODCaloCells*>(&obj);
  if(!robj)return; // not an AliAODCaloCells
  *robj = *this;

}

AliVCaloCells *AliAODCaloCells::CopyCaloCells(Bool_t all = kTRUE) const {

  // copy the calo cells into a new object. If option all=FALSE, just the object type,
  // for mixing

  AliVCaloCells *obj =  new AliAODCaloCells();

  if(all){
    obj->SetName (GetName()) ;
    obj->SetTitle(GetTitle()) ;
    obj->SetType (GetType()) ;

    obj->SetNumberOfCells(fNCells);
    for (Short_t i = 0; i < fNCells; i++)
      obj->SetCell(i,fCellNumber[i],fAmplitude[i],-1);
  }

  return obj;

}

void AliAODCaloCells::CreateContainer(Short_t nCells)
{
  // function that creates container to store calorimeter cell data

  DeleteContainer();

  if (nCells <= 0) {
    fNCells = 0;
    return;
  }

  fNCells = nCells;

  fCellNumber = new Short_t[fNCells];
  fAmplitude  = new Double32_t[fNCells];

  // set to zero
  for(int i = 0;i<fNCells;++i){
    fAmplitude[i] = fCellNumber[i] = 0 ;
  }
}

void AliAODCaloCells::DeleteContainer()
{
  // deletes allocated memory

  if (fCellNumber)
  {
    delete[] fCellNumber;
    fCellNumber = NULL;
  }

  if (fAmplitude)
  {
    delete[] fAmplitude;
    fAmplitude = NULL;
  }

  fNCells = 0;
  fIsSorted = kFALSE;
}

void AliAODCaloCells::Sort()
{
  // sort the cell array by cell number

  Int_t *idxArray = new Int_t[fNCells];
  TMath::Sort(fNCells,fCellNumber,idxArray,kFALSE);

  Short_t    *newIndex     = new Short_t[fNCells];
  Double32_t *newAmplitude = new Double32_t[fNCells];
  for (Int_t i=0; i < fNCells; i++) {
    newIndex[i]     = fCellNumber[idxArray[i]];
    newAmplitude[i] = fAmplitude[idxArray[i]];
  }
  delete [] fCellNumber;
  delete [] fAmplitude;
  fCellNumber = newIndex;
  fAmplitude  = newAmplitude;

  delete [] idxArray;

  fIsSorted = kTRUE;
}

Bool_t AliAODCaloCells::SetCell(Short_t pos, Short_t cellNumber, Double32_t amplitude, Double32_t /*time*/)
{
  // Sets a cell at the given position

  if (pos>=0 && pos < fNCells) {
    fCellNumber[pos] = cellNumber;
    fAmplitude[pos]  = amplitude;
    fIsSorted = kFALSE;
    return kTRUE;
  } else {
    return kFALSE;
  }
}
<|endoftext|>


<commit_before>#include <core/stdafx.h>
#include <core/interpret/flags.h>
#include <core/utility/strings.h>
#include <core/addin/addin.h>
#include <core/addin/mfcmapi.h>

namespace flags
{
	// Interprets a flag value according to a flag name and returns a string
	// Will not return a string if the flag name is not recognized
	std::wstring InterpretFlags(ULONG ulFlagName, LONG lFlagValue)
	{
		ULONG ulCurEntry = 0;

		if (FlagArray.empty()) return L"";

		while (ulCurEntry < FlagArray.size() && FlagArray[ulCurEntry].ulFlagName != ulFlagName)
		{
			ulCurEntry++;
		}

		// Don't run off the end of the array
		if (FlagArray.size() == ulCurEntry) return L"";
		if (FlagArray[ulCurEntry].ulFlagName != ulFlagName) return L"";

		// We've matched our flag name to the array - we SHOULD return a string at this point
		auto bNeedSeparator = false;

		auto lTempValue = lFlagValue;
		std::wstring szTempString;
		for (; FlagArray[ulCurEntry].ulFlagName == ulFlagName; ulCurEntry++)
		{
			if (flagFLAG == FlagArray[ulCurEntry].ulFlagType)
			{
				if (FlagArray[ulCurEntry].lFlagValue & lTempValue)
				{
					if (bNeedSeparator)
					{
						szTempString += L" | "; // STRING_OK
					}

					szTempString += FlagArray[ulCurEntry].lpszName;
					lTempValue &= ~FlagArray[ulCurEntry].lFlagValue;
					bNeedSeparator = true;
				}
			}
			else if (flagVALUE == FlagArray[ulCurEntry].ulFlagType)
			{
				if (FlagArray[ulCurEntry].lFlagValue == lTempValue)
				{
					if (bNeedSeparator)
					{
						szTempString += L" | "; // STRING_OK
					}

					szTempString += FlagArray[ulCurEntry].lpszName;
					lTempValue = 0;
					bNeedSeparator = true;
				}
			}
			else if (flagVALUEHIGHBYTES == FlagArray[ulCurEntry].ulFlagType)
			{
				if (FlagArray[ulCurEntry].lFlagValue == (lTempValue >> 16 & 0xFFFF))
				{
					if (bNeedSeparator)
					{
						szTempString += L" | "; // STRING_OK
					}

					szTempString += FlagArray[ulCurEntry].lpszName;
					lTempValue = lTempValue - (FlagArray[ulCurEntry].lFlagValue << 16);
					bNeedSeparator = true;
				}
			}
			else if (flagVALUE3RDBYTE == FlagArray[ulCurEntry].ulFlagType)
			{
				if (FlagArray[ulCurEntry].lFlagValue == (lTempValue >> 8 & 0xFF))
				{
					if (bNeedSeparator)
					{
						szTempString += L" | "; // STRING_OK
					}

					szTempString += FlagArray[ulCurEntry].lpszName;
					lTempValue = lTempValue - (FlagArray[ulCurEntry].lFlagValue << 8);
					bNeedSeparator = true;
				}
			}
			else if (flagVALUE4THBYTE == FlagArray[ulCurEntry].ulFlagType)
			{
				if (FlagArray[ulCurEntry].lFlagValue == (lTempValue & 0xFF))
				{
					if (bNeedSeparator)
					{
						szTempString += L" | "; // STRING_OK
					}

					szTempString += FlagArray[ulCurEntry].lpszName;
					lTempValue = lTempValue - FlagArray[ulCurEntry].lFlagValue;
					bNeedSeparator = true;
				}
			}
			else if (flagVALUELOWERNIBBLE == FlagArray[ulCurEntry].ulFlagType)
			{
				if (FlagArray[ulCurEntry].lFlagValue == (lTempValue & 0x0F))
				{
					if (bNeedSeparator)
					{
						szTempString += L" | "; // STRING_OK
					}

					szTempString += FlagArray[ulCurEntry].lpszName;
					lTempValue = lTempValue - FlagArray[ulCurEntry].lFlagValue;
					bNeedSeparator = true;
				}
			}
			else if (flagCLEARBITS == FlagArray[ulCurEntry].ulFlagType)
			{
				// find any bits we need to clear
				const auto lClearedBits = FlagArray[ulCurEntry].lFlagValue & lTempValue;
				// report what we found
				if (0 != lClearedBits)
				{
					if (bNeedSeparator)
					{
						szTempString += L" | "; // STRING_OK
					}

					szTempString += strings::format(L"0x%X", lClearedBits); // STRING_OK
						// clear the bits out
					lTempValue &= ~FlagArray[ulCurEntry].lFlagValue;
					bNeedSeparator = true;
				}
			}
		}

		// We know if we've found anything already because bNeedSeparator will be true
		// If bNeedSeparator isn't true, we found nothing and need to tack on
		// Otherwise, it's true, and we only tack if lTempValue still has something in it
		if (!bNeedSeparator || lTempValue)
		{
			if (bNeedSeparator)
			{
				szTempString += L" | "; // STRING_OK
			}

			szTempString += strings::format(L"0x%X", lTempValue); // STRING_OK
		}

		return szTempString;
	}

	// Returns a list of all known flags/values for a flag name.
	// For instance, for flagFuzzyLevel, would return:
	// \r\n0x00000000 FL_FULLSTRING\r\n\
	 // 0x00000001 FL_SUBSTRING\r\n\
	 // 0x00000002 FL_PREFIX\r\n\
	 // 0x00010000 FL_IGNORECASE\r\n\
	 // 0x00020000 FL_IGNORENONSPACE\r\n\
	 // 0x00040000 FL_LOOSE
	//
	// Since the string is always appended to a prompt we include \r\n at the start
	std::wstring AllFlagsToString(ULONG ulFlagName, bool bHex)
	{
		std::wstring szFlagString;
		if (!ulFlagName) return szFlagString;
		if (FlagArray.empty()) return szFlagString;

		ULONG ulCurEntry = 0;
		std::wstring szTempString;

		while (ulCurEntry < FlagArray.size() && FlagArray[ulCurEntry].ulFlagName != ulFlagName)
		{
			ulCurEntry++;
		}

		if (ulCurEntry == FlagArray.size() || FlagArray[ulCurEntry].ulFlagName != ulFlagName) return szFlagString;

		// We've matched our flag name to the array - we SHOULD return a string at this point
		for (; FlagArray[ulCurEntry].ulFlagName == ulFlagName; ulCurEntry++)
		{
			if (flagCLEARBITS == FlagArray[ulCurEntry].ulFlagType)
			{
				// keep going
			}
			else
			{
				if (bHex)
				{
					szFlagString += strings::formatmessage(
						IDS_FLAGTOSTRINGHEX, FlagArray[ulCurEntry].lFlagValue, FlagArray[ulCurEntry].lpszName);
				}
				else
				{
					szFlagString += strings::formatmessage(
						IDS_FLAGTOSTRINGDEC, FlagArray[ulCurEntry].lFlagValue, FlagArray[ulCurEntry].lpszName);
				}
			}
		}

		return szFlagString;
	}
} // namespace flags
<commit_msg>rework flag parsers, increase coverage<commit_after>#include <core/stdafx.h>
#include <core/interpret/flags.h>
#include <core/utility/strings.h>
#include <core/addin/addin.h>
#include <core/addin/mfcmapi.h>

namespace flags
{
	// Interprets a flag value according to a flag name and returns a string
	// Will not return a string if the flag name is not recognized
	std::wstring InterpretFlags(ULONG ulFlagName, LONG lFlagValue)
	{
		ULONG ulCurEntry = 0;

		if (FlagArray.empty()) return L"";

		while (ulCurEntry < FlagArray.size() && FlagArray[ulCurEntry].ulFlagName != ulFlagName)
		{
			ulCurEntry++;
		}

		// Don't run off the end of the array
		if (FlagArray.size() == ulCurEntry) return L"";
		if (FlagArray[ulCurEntry].ulFlagName != ulFlagName) return L"";

		// We've matched our flag name to the array - we SHOULD return a string at this point
		auto flags = std::vector<std::wstring>{};
		auto lTempValue = lFlagValue;
		for (; FlagArray[ulCurEntry].ulFlagName == ulFlagName; ulCurEntry++)
		{
			if (flagFLAG == FlagArray[ulCurEntry].ulFlagType)
			{
				if (FlagArray[ulCurEntry].lFlagValue & lTempValue)
				{
					flags.push_back(FlagArray[ulCurEntry].lpszName);
					lTempValue &= ~FlagArray[ulCurEntry].lFlagValue;
				}
			}
			else if (flagVALUE == FlagArray[ulCurEntry].ulFlagType)
			{
				if (FlagArray[ulCurEntry].lFlagValue == lTempValue)
				{
					flags.push_back(FlagArray[ulCurEntry].lpszName);
					lTempValue = 0;
				}
			}
			else if (flagVALUEHIGHBYTES == FlagArray[ulCurEntry].ulFlagType)
			{
				if (FlagArray[ulCurEntry].lFlagValue == (lTempValue >> 16 & 0xFFFF))
				{
					flags.push_back(FlagArray[ulCurEntry].lpszName);
					lTempValue = lTempValue - (FlagArray[ulCurEntry].lFlagValue << 16);
				}
			}
			else if (flagVALUE3RDBYTE == FlagArray[ulCurEntry].ulFlagType)
			{
				if (FlagArray[ulCurEntry].lFlagValue == (lTempValue >> 8 & 0xFF))
				{
					flags.push_back(FlagArray[ulCurEntry].lpszName);
					lTempValue = lTempValue - (FlagArray[ulCurEntry].lFlagValue << 8);
				}
			}
			else if (flagVALUE4THBYTE == FlagArray[ulCurEntry].ulFlagType)
			{
				if (FlagArray[ulCurEntry].lFlagValue == (lTempValue & 0xFF))
				{
					flags.push_back(FlagArray[ulCurEntry].lpszName);
					lTempValue = lTempValue - FlagArray[ulCurEntry].lFlagValue;
				}
			}
			else if (flagVALUELOWERNIBBLE == FlagArray[ulCurEntry].ulFlagType)
			{
				if (FlagArray[ulCurEntry].lFlagValue == (lTempValue & 0x0F))
				{
					flags.push_back(FlagArray[ulCurEntry].lpszName);
					lTempValue = lTempValue - FlagArray[ulCurEntry].lFlagValue;
				}
			}
			else if (flagCLEARBITS == FlagArray[ulCurEntry].ulFlagType)
			{
				// find any bits we need to clear
				const auto lClearedBits = FlagArray[ulCurEntry].lFlagValue & lTempValue;
				// report what we found
				if (0 != lClearedBits)
				{
					flags.push_back(strings::format(L"0x%X", lClearedBits)); // STRING_OK
						// clear the bits out
					lTempValue &= ~FlagArray[ulCurEntry].lFlagValue;
				}
			}
		}

		if (lTempValue || flags.empty())
		{
			flags.push_back(strings::format(L"0x%X", lTempValue)); // STRING_OK
		}

		return strings::join(flags, L" | ");
	}

	// Returns a list of all known flags/values for a flag name.
	// For instance, for flagFuzzyLevel, would return:
	// \r\n0x00000000 FL_FULLSTRING\r\n\
	 // 0x00000001 FL_SUBSTRING\r\n\
	 // 0x00000002 FL_PREFIX\r\n\
	 // 0x00010000 FL_IGNORECASE\r\n\
	 // 0x00020000 FL_IGNORENONSPACE\r\n\
	 // 0x00040000 FL_LOOSE
	//
	// Since the string is always appended to a prompt we include \r\n at the start
	std::wstring AllFlagsToString(ULONG ulFlagName, bool bHex)
	{
		if (!ulFlagName) return L"";
		if (FlagArray.empty()) return L"";

		ULONG ulCurEntry = 0;

		while (ulCurEntry < FlagArray.size() && FlagArray[ulCurEntry].ulFlagName != ulFlagName)
		{
			ulCurEntry++;
		}

		if (ulCurEntry == FlagArray.size() || FlagArray[ulCurEntry].ulFlagName != ulFlagName) return L"";

		// We've matched our flag name to the array - we SHOULD return a string at this point
		auto flags = std::vector<std::wstring>{};
		for (; FlagArray[ulCurEntry].ulFlagName == ulFlagName; ulCurEntry++)
		{
			if (flagCLEARBITS == FlagArray[ulCurEntry].ulFlagType)
			{
				// keep going
			}
			else
			{
				if (bHex)
				{
					flags.push_back(strings::formatmessage(
						IDS_FLAGTOSTRINGHEX, FlagArray[ulCurEntry].lFlagValue, FlagArray[ulCurEntry].lpszName));
				}
				else
				{
					flags.push_back(strings::formatmessage(
						IDS_FLAGTOSTRINGDEC, FlagArray[ulCurEntry].lFlagValue, FlagArray[ulCurEntry].lpszName));
				}
			}
		}

		return strings::join(flags, L"");
	}
} // namespace flags
<|endoftext|>


<commit_before>

/* ring_test.cpp
a test consol to see if ringbuffer's exceptions are working fine
with exceeding push and pop options
*/

#include <stdio.h>
#include <stdlib.h>
#include <iostream>

#include "ring.h"

using namespace std;

void main()
{
	const int buffer_size = 5;
	const int push_size = 7;
	int pop_size = 12;

	ptr_t data[buffer_size];
	ptr_t pop_data;

	struct ring* ring_buffer = ring_create( buffer_size );

	for( int i = 0; i < push_size  ; i++)
	{

		data[i] = new int[1];
		//data[i] = new char[1];

		int err = ring_push(ring_buffer, &data[i]);

		if ( err == 0 )
		{
			printf("push data %d = %d \n", i, &data[i]);
		}
		else
		{
			printf("push %d failed \n ", i);
		}
	}

	for( int i = 0; i < pop_size  ; i++)
	{
		pop_data = ring_pop(ring_buffer);

		if(pop_data == NULL)
		{
			printf("pop %d failed \n" , i);
		}
		else
		{
			printf("pop data %d = %d\n", i, pop_data);
		}
	}

//	enter any word and hit enter to close the promp
	std::cout << "enter any word and hit enter to close the promp" << std::endl ;
	int end;
	std::cin >> end ;

}
<commit_msg>Style Updated<commit_after>

/* ring_test.cpp
a test consol to see if ringbuffer's exceptions are working fine
with exceeding push and pop options
*/
#include <stdio.h>
#include <stdlib.h>
#include <iostream>

#include "ring.h"

using namespace std;

void main()
{
	const int buffer_size = 5;
	const int push_size = 7;
	int pop_size = 12;

	void* data[buffer_size];
	void* pop_data;

	struct ring* ring_buffer = ring_create( buffer_size );

	for( int i = 0; i < push_size  ; i++)
	{

		data[i] = new int[1];
		//data[i] = new char[1];

		int err = ring_push(ring_buffer, &data[i]);

		if ( err == 0 ){
			printf("push data %d = %d \n", i, &data[i]);
		}
		else{
			printf("push %d failed \n ", i);
		}
	}

	for( int i = 0; i < pop_size  ; i++)
	{
		pop_data = ring_pop(ring_buffer);

		if(pop_data == NULL){
			printf("pop %d failed \n" , i);
		}
		else{
			printf("pop data %d = %d\n", i, pop_data);
		}
	}

	//	enter any word and hit enter to close the promp
	std::cout << "enter any word and hit enter to close the promp" << std::endl ;
	int end;
	std::cin >> end ;

}
<|endoftext|>


<commit_before>#include "primal_dual.hpp"

namespace mlpack {
namespace optimization {

PrimalDualSolver::PrimalDualSolver(const SDP& sdp)
  : sdp(sdp),
    X0(arma::eye<arma::mat>(sdp.N(), sdp.N())),
    ysparse0(arma::ones<arma::vec>(sdp.NumSparseConstraints())),
    ydense0(arma::ones<arma::vec>(sdp.NumDenseConstraints())),
    Z0(arma::eye<arma::mat>(sdp.N(), sdp.N())),
    sigma(0.5),
    tau(0.5),
    normXzTol(1e-7),
    primalInfeasTol(1e-7),
    dualInfeasTol(1e-7),
    maxIterations(1000)
{

}

PrimalDualSolver::PrimalDualSolver(const SDP& sdp,
                                   const arma::mat& X0,
                                   const arma::vec& ysparse0,
                                   const arma::vec& ydense0,
                                   const arma::mat& Z0)
  : sdp(sdp),
    X0(X0),
    ysparse0(ysparse0),
    ydense0(ydense0),
    Z0(Z0),
    sigma(0.5),
    tau(0.5),
    normXzTol(1e-7),
    primalInfeasTol(1e-7),
    dualInfeasTol(1e-7),
    maxIterations(1000)
{
  if (X0.n_rows != sdp.N() || X0.n_cols != sdp.N())
    Log::Fatal << "PrimalDualSolver::PrimalDualSolver(): "
      << "X0 needs to be square n x n matrix"
      << std::endl;

  if (ysparse0.n_elem != sdp.NumSparseConstraints())
    Log::Fatal << "PrimalDualSolver::PrimalDualSolver(): "
      << "ysparse0 needs to have the same length as the number of sparse constraints"
      << std::endl;

  if (ydense0.n_elem != sdp.NumDenseConstraints())
    Log::Fatal << "PrimalDualSolver::PrimalDualSolver(): "
      << "ydense0 needs to have the same length as the number of dense constraints"
      << std::endl;

  if (Z0.n_rows != sdp.N() || Z0.n_cols != sdp.N())
    Log::Fatal << "PrimalDualSolver::PrimalDualSolver(): "
      << "Z0 needs to be square n x n matrix"
      << std::endl;
}

static inline arma::mat
DenseFromSparse(const arma::sp_mat& input)
{
  return arma::mat(input);
}

static inline double
AlphaHat(const arma::mat& A, const arma::mat& dA)
{
  // note: arma::chol(A) returns an upper triangular matrix (instead of the
  // usual lower triangular)
  const arma::mat L = arma::trimatl(arma::chol(A).t());
  const arma::mat Linv = L.i();
  const arma::vec evals = arma::eig_sym(-Linv * dA * Linv.t());
  const double alphahatinv = evals(evals.n_elem - 1);
  return 1. / alphahatinv;
}

/**
 * Solve the following Lyapunov equation (for X)
 *
 *   AX + XA = H
 *
 * where A, H are symmetric matrices
 *
 */
static inline void
SolveLyapunov(arma::mat& X, const arma::mat& A, const arma::mat& H)
{
  arma::syl(X, A, A, -H);
}

double PrimalDualSolver::Optimize(arma::mat& X,
                                  arma::vec& ysparse,
                                  arma::vec& ydense,
                                  arma::mat& Z)
{
  const size_t n = sdp.N();
  const size_t n2bar = sdp.N2bar();

  // TODO: implementation does not take adv of sparsity yet

  arma::mat Asparse(sdp.NumSparseConstraints(), n2bar);
  arma::vec Ai;

  for (size_t i = 0; i < sdp.NumSparseConstraints(); i++)
  {
    math::Svec(DenseFromSparse(sdp.SparseA()[i]), Ai);
    Asparse.row(i) = Ai.t();
  }

  arma::mat Adense(sdp.NumDenseConstraints(), n2bar);
  for (size_t i = 0; i < sdp.NumDenseConstraints(); i++)
  {
    math::Svec(sdp.DenseA()[i], Ai);
    Adense.row(i) = Ai.t();
  }

  arma::vec scsparse;
  if (sdp.HasSparseObjective())
    math::Svec(DenseFromSparse(sdp.SparseC()), scsparse);

  arma::vec scdense;
  if (sdp.HasDenseObjective())
    math::Svec(sdp.DenseC(), scdense);

  X = X0;
  ysparse = ysparse0;
  ydense = ydense0;
  Z = Z0;

  arma::vec sx, sz, dy, dysparse, dydense, dsx, dsz;
  arma::mat dX, dZ;

  math::Svec(X, sx);
  math::Svec(Z, sz);

  arma::vec rp, rd, rc, gk, Einv_Frd_rc, Einv_Frd_ATdy_rc, rhs;

  arma::mat Rc, E, F, Einv_F_AsparseT, Einv_F_AdenseT, Gk,
            M, Einv_Frd_rc_Mat, Frd_rc_Mat, Frd_ATdy_rc_Mat,
            Einv_Frd_ATdy_rc_Mat;

  rp.set_size(sdp.NumConstraints());
  rhs.set_size(sdp.NumConstraints());

  Einv_F_AsparseT.set_size(n2bar, sdp.NumSparseConstraints());
  Einv_F_AdenseT.set_size(n2bar, sdp.NumDenseConstraints());
  M.set_size(sdp.NumConstraints(), sdp.NumConstraints());

  for (size_t iteration = 0; iteration < maxIterations; iteration++)
  {

    const double mu = sigma * arma::dot(sx, sz) / n;

    if (sdp.NumSparseConstraints())
      rp(arma::span(0, sdp.NumSparseConstraints() - 1)) =
        sdp.SparseB() - Asparse * sx;
    if (sdp.NumDenseConstraints())
      rp(arma::span(sdp.NumSparseConstraints(), sdp.NumConstraints() - 1)) =
          sdp.DenseB() - Adense * sx;

    //std::cout << "rp" << std::endl;
    //std::cout << rp << std::endl;

    rd = - sz - Asparse.t() * ysparse - Adense.t() * ydense;
    if (sdp.HasSparseObjective())
      rd += scsparse;
    if (sdp.HasDenseObjective())
      rd += scdense;

    //std::cout << "rd" << std::endl;
    //std::cout << rd << std::endl;

    Rc = mu*arma::eye<arma::mat>(n, n) - 0.5*(X*Z + Z*X);
    math::Svec(Rc, rc);

    //std::cout << "rc" << std::endl;
    //std::cout << rc << std::endl;

    math::SymKronId(Z, E);
    math::SymKronId(X, F);

    //std::cout << "E" << std::endl;
    //std::cout << E << std::endl;

    //std::cout << "F" << std::endl;
    //std::cout << F << std::endl;

    for (size_t i = 0; i < sdp.NumSparseConstraints(); i++)
    {
      SolveLyapunov(Gk, Z, X * sdp.SparseA()[i] + sdp.SparseA()[i] * X);
      math::Svec(Gk, gk);
      Einv_F_AsparseT.col(i) = gk;
    }

    //std::cout << "Einv_F_AsparseT" << std::endl;
    //std::cout << Einv_F_AsparseT << std::endl;

    for (size_t i = 0; i < sdp.NumDenseConstraints(); i++)
    {
      SolveLyapunov(Gk, Z, X * sdp.DenseA()[i] + sdp.DenseA()[i] * X);
      math::Svec(Gk, gk);
      Einv_F_AdenseT.col(i) = gk;
    }

    if (sdp.NumSparseConstraints())
    {
      M.submat(arma::span(0,
                          sdp.NumSparseConstraints() - 1),
               arma::span(0,
                          sdp.NumSparseConstraints() - 1)) =
        Asparse * Einv_F_AsparseT;
      if (sdp.NumDenseConstraints())
      {
        M.submat(arma::span(0,
                            sdp.NumSparseConstraints() - 1),
                 arma::span(sdp.NumSparseConstraints(),
                            sdp.NumConstraints() - 1)) =
          Asparse * Einv_F_AdenseT;
      }
    }
    if (sdp.NumDenseConstraints())
    {
      if (sdp.NumSparseConstraints())
      {
        M.submat(arma::span(sdp.NumSparseConstraints(),
                            sdp.NumConstraints() - 1),
                 arma::span(0,
                            sdp.NumSparseConstraints() - 1)) =
          Adense * Einv_F_AsparseT;
      }
      M.submat(arma::span(sdp.NumSparseConstraints(),
                          sdp.NumConstraints() - 1),
               arma::span(sdp.NumSparseConstraints(),
                          sdp.NumConstraints() - 1)) =
        Adense * Einv_F_AdenseT;
    }

    //std::cout << "M" << std::endl;
    //std::cout << M << std::endl;

    math::Smat(F * rd - rc, Frd_rc_Mat);
    SolveLyapunov(Einv_Frd_rc_Mat, Z, 2. * Frd_rc_Mat);
    math::Svec(Einv_Frd_rc_Mat, Einv_Frd_rc);

    rhs = rp;
    if (sdp.NumSparseConstraints())
      rhs(arma::span(0, sdp.NumSparseConstraints() - 1)) += Asparse * Einv_Frd_rc;
    if (sdp.NumDenseConstraints())
      rhs(arma::span(sdp.NumSparseConstraints(), sdp.NumConstraints() - 1)) += Adense * Einv_Frd_rc;

    // TODO(stephentu): use a more efficient method (e.g. LU decomposition)
    //std::cout << "rhs" << std::endl;
    //std::cout << rhs << std::endl;

    arma::solve(dy, M, rhs);
    if (sdp.NumSparseConstraints())
      dysparse = dy(arma::span(0, sdp.NumSparseConstraints() - 1));
    if (sdp.NumDenseConstraints())
      dydense = dy(arma::span(sdp.NumSparseConstraints(), sdp.NumConstraints() - 1));
    //std::cout << "dy" << std::endl;
    //std::cout << dy << std::endl;

    math::Smat(F * (rd - Asparse.t() * dysparse - Adense.t() * dydense) - rc, Frd_ATdy_rc_Mat);
    SolveLyapunov(Einv_Frd_ATdy_rc_Mat, Z, 2. * Frd_ATdy_rc_Mat);
    math::Svec(Einv_Frd_ATdy_rc_Mat, Einv_Frd_ATdy_rc);
    dsx = -Einv_Frd_ATdy_rc;

    //std::cout << "dsx" << std::endl;
    //std::cout << dsx << std::endl;

    dsz = rd - Asparse.t() * dysparse - Adense.t() * dydense;

    //std::cout << "dsz" << std::endl;
    //std::cout << dsz << std::endl;

    math::Smat(dsx, dX);
    math::Smat(dsz, dZ);

    double alphahatX = AlphaHat(X, dX);
    if (alphahatX < 0.)
      // dX is PSD
      alphahatX = 1.;

    double alphahatZ = AlphaHat(Z, dZ);
    if (alphahatZ < 0.)
      // dZ is PSD
      alphahatZ = 1.;

    const double alpha = std::min(1., tau * alphahatX);
    const double beta = std::min(1., tau * alphahatZ);

    X += alpha * dX;
    math::Svec(X, sx);
    ysparse += beta * dysparse;
    ydense += beta * dydense;
    Z += beta * dZ;
    math::Svec(Z, sz);

    const double norm_XZ = arma::norm(X * Z, "fro");

    const double sparse_primal_infeas = arma::norm(sdp.SparseB() - Asparse * sx, 2);
    const double dense_primal_infeas = arma::norm(sdp.DenseB() - Adense * sx, 2);
    const double primal_infeas = sqrt(
        sparse_primal_infeas * sparse_primal_infeas +
        dense_primal_infeas * dense_primal_infeas);

    double primal_obj = 0.;
    if (sdp.HasSparseObjective())
      primal_obj += arma::dot(sdp.SparseC(), X);
    if (sdp.HasDenseObjective())
      primal_obj += arma::dot(sdp.DenseC(), X);

    const double dual_obj =
      arma::dot(sdp.SparseB(), ysparse) +
      arma::dot(sdp.DenseB(), ydense);

    const double duality_gap = primal_obj - dual_obj;

    Log::Debug
      << "iter=" << iteration + 1 << ", "
      << "primal=" << primal_obj << ", "
      << "dual=" << dual_obj << ", "
      << "gap=" << duality_gap << ", "
      << "||XZ||=" << norm_XZ << ", "
      << "primal_infeas=" << primal_infeas << ", "
      << "mu=" << mu
      << std::endl;

    if (norm_XZ <= normXzTol &&
        primal_infeas <= primalInfeasTol)
      return primal_obj;
  }

  Log::Warn << "did not converge" << std::endl;
  return -1;
}

} // namespace optimization
} // namespace mlpack
<commit_msg>add a check for dual feasibility<commit_after>#include "primal_dual.hpp"

namespace mlpack {
namespace optimization {

PrimalDualSolver::PrimalDualSolver(const SDP& sdp)
  : sdp(sdp),
    X0(arma::eye<arma::mat>(sdp.N(), sdp.N())),
    ysparse0(arma::ones<arma::vec>(sdp.NumSparseConstraints())),
    ydense0(arma::ones<arma::vec>(sdp.NumDenseConstraints())),
    Z0(arma::eye<arma::mat>(sdp.N(), sdp.N())),
    sigma(0.5),
    tau(0.5),
    normXzTol(1e-7),
    primalInfeasTol(1e-7),
    dualInfeasTol(1e-7),
    maxIterations(1000)
{

}

PrimalDualSolver::PrimalDualSolver(const SDP& sdp,
                                   const arma::mat& X0,
                                   const arma::vec& ysparse0,
                                   const arma::vec& ydense0,
                                   const arma::mat& Z0)
  : sdp(sdp),
    X0(X0),
    ysparse0(ysparse0),
    ydense0(ydense0),
    Z0(Z0),
    sigma(0.5),
    tau(0.5),
    normXzTol(1e-7),
    primalInfeasTol(1e-7),
    dualInfeasTol(1e-7),
    maxIterations(1000)
{
  if (X0.n_rows != sdp.N() || X0.n_cols != sdp.N())
    Log::Fatal << "PrimalDualSolver::PrimalDualSolver(): "
      << "X0 needs to be square n x n matrix"
      << std::endl;

  if (ysparse0.n_elem != sdp.NumSparseConstraints())
    Log::Fatal << "PrimalDualSolver::PrimalDualSolver(): "
      << "ysparse0 needs to have the same length as the number of sparse constraints"
      << std::endl;

  if (ydense0.n_elem != sdp.NumDenseConstraints())
    Log::Fatal << "PrimalDualSolver::PrimalDualSolver(): "
      << "ydense0 needs to have the same length as the number of dense constraints"
      << std::endl;

  if (Z0.n_rows != sdp.N() || Z0.n_cols != sdp.N())
    Log::Fatal << "PrimalDualSolver::PrimalDualSolver(): "
      << "Z0 needs to be square n x n matrix"
      << std::endl;
}

static inline arma::mat
DenseFromSparse(const arma::sp_mat& input)
{
  return arma::mat(input);
}

static inline double
AlphaHat(const arma::mat& A, const arma::mat& dA)
{
  // note: arma::chol(A) returns an upper triangular matrix (instead of the
  // usual lower triangular)
  const arma::mat L = arma::trimatl(arma::chol(A).t());
  const arma::mat Linv = L.i();
  const arma::vec evals = arma::eig_sym(-Linv * dA * Linv.t());
  const double alphahatinv = evals(evals.n_elem - 1);
  return 1. / alphahatinv;
}

/**
 * Solve the following Lyapunov equation (for X)
 *
 *   AX + XA = H
 *
 * where A, H are symmetric matrices
 *
 */
static inline void
SolveLyapunov(arma::mat& X, const arma::mat& A, const arma::mat& H)
{
  arma::syl(X, A, A, -H);
}

double PrimalDualSolver::Optimize(arma::mat& X,
                                  arma::vec& ysparse,
                                  arma::vec& ydense,
                                  arma::mat& Z)
{
  const size_t n = sdp.N();
  const size_t n2bar = sdp.N2bar();

  // TODO: implementation does not take adv of sparsity yet

  arma::mat Asparse(sdp.NumSparseConstraints(), n2bar);
  arma::vec Ai;

  for (size_t i = 0; i < sdp.NumSparseConstraints(); i++)
  {
    math::Svec(DenseFromSparse(sdp.SparseA()[i]), Ai);
    Asparse.row(i) = Ai.t();
  }

  arma::mat Adense(sdp.NumDenseConstraints(), n2bar);
  for (size_t i = 0; i < sdp.NumDenseConstraints(); i++)
  {
    math::Svec(sdp.DenseA()[i], Ai);
    Adense.row(i) = Ai.t();
  }

  arma::vec scsparse;
  if (sdp.HasSparseObjective())
    math::Svec(DenseFromSparse(sdp.SparseC()), scsparse);

  arma::vec scdense;
  if (sdp.HasDenseObjective())
    math::Svec(sdp.DenseC(), scdense);

  X = X0;
  ysparse = ysparse0;
  ydense = ydense0;
  Z = Z0;

  arma::vec sx, sz, dy, dysparse, dydense, dsx, dsz;
  arma::mat dX, dZ;

  math::Svec(X, sx);
  math::Svec(Z, sz);

  arma::vec rp, rd, rc, gk, Einv_Frd_rc, Einv_Frd_ATdy_rc, rhs;

  arma::mat Rc, E, F, Einv_F_AsparseT, Einv_F_AdenseT, Gk,
            M, Einv_Frd_rc_Mat, Frd_rc_Mat, Frd_ATdy_rc_Mat,
            Einv_Frd_ATdy_rc_Mat, DualCheck;

  rp.set_size(sdp.NumConstraints());
  rhs.set_size(sdp.NumConstraints());

  Einv_F_AsparseT.set_size(n2bar, sdp.NumSparseConstraints());
  Einv_F_AdenseT.set_size(n2bar, sdp.NumDenseConstraints());
  M.set_size(sdp.NumConstraints(), sdp.NumConstraints());

  for (size_t iteration = 0; iteration < maxIterations; iteration++)
  {

    const double mu = sigma * arma::dot(sx, sz) / n;

    if (sdp.NumSparseConstraints())
      rp(arma::span(0, sdp.NumSparseConstraints() - 1)) =
        sdp.SparseB() - Asparse * sx;
    if (sdp.NumDenseConstraints())
      rp(arma::span(sdp.NumSparseConstraints(), sdp.NumConstraints() - 1)) =
          sdp.DenseB() - Adense * sx;

    //std::cout << "rp" << std::endl;
    //std::cout << rp << std::endl;

    rd = - sz - Asparse.t() * ysparse - Adense.t() * ydense;
    if (sdp.HasSparseObjective())
      rd += scsparse;
    if (sdp.HasDenseObjective())
      rd += scdense;

    //std::cout << "rd" << std::endl;
    //std::cout << rd << std::endl;

    Rc = mu*arma::eye<arma::mat>(n, n) - 0.5*(X*Z + Z*X);
    math::Svec(Rc, rc);

    //std::cout << "rc" << std::endl;
    //std::cout << rc << std::endl;

    math::SymKronId(Z, E);
    math::SymKronId(X, F);

    //std::cout << "E" << std::endl;
    //std::cout << E << std::endl;

    //std::cout << "F" << std::endl;
    //std::cout << F << std::endl;

    for (size_t i = 0; i < sdp.NumSparseConstraints(); i++)
    {
      SolveLyapunov(Gk, Z, X * sdp.SparseA()[i] + sdp.SparseA()[i] * X);
      math::Svec(Gk, gk);
      Einv_F_AsparseT.col(i) = gk;
    }

    //std::cout << "Einv_F_AsparseT" << std::endl;
    //std::cout << Einv_F_AsparseT << std::endl;

    for (size_t i = 0; i < sdp.NumDenseConstraints(); i++)
    {
      SolveLyapunov(Gk, Z, X * sdp.DenseA()[i] + sdp.DenseA()[i] * X);
      math::Svec(Gk, gk);
      Einv_F_AdenseT.col(i) = gk;
    }

    if (sdp.NumSparseConstraints())
    {
      M.submat(arma::span(0,
                          sdp.NumSparseConstraints() - 1),
               arma::span(0,
                          sdp.NumSparseConstraints() - 1)) =
        Asparse * Einv_F_AsparseT;
      if (sdp.NumDenseConstraints())
      {
        M.submat(arma::span(0,
                            sdp.NumSparseConstraints() - 1),
                 arma::span(sdp.NumSparseConstraints(),
                            sdp.NumConstraints() - 1)) =
          Asparse * Einv_F_AdenseT;
      }
    }
    if (sdp.NumDenseConstraints())
    {
      if (sdp.NumSparseConstraints())
      {
        M.submat(arma::span(sdp.NumSparseConstraints(),
                            sdp.NumConstraints() - 1),
                 arma::span(0,
                            sdp.NumSparseConstraints() - 1)) =
          Adense * Einv_F_AsparseT;
      }
      M.submat(arma::span(sdp.NumSparseConstraints(),
                          sdp.NumConstraints() - 1),
               arma::span(sdp.NumSparseConstraints(),
                          sdp.NumConstraints() - 1)) =
        Adense * Einv_F_AdenseT;
    }

    //std::cout << "M" << std::endl;
    //std::cout << M << std::endl;

    math::Smat(F * rd - rc, Frd_rc_Mat);
    SolveLyapunov(Einv_Frd_rc_Mat, Z, 2. * Frd_rc_Mat);
    math::Svec(Einv_Frd_rc_Mat, Einv_Frd_rc);

    rhs = rp;
    if (sdp.NumSparseConstraints())
      rhs(arma::span(0, sdp.NumSparseConstraints() - 1)) += Asparse * Einv_Frd_rc;
    if (sdp.NumDenseConstraints())
      rhs(arma::span(sdp.NumSparseConstraints(), sdp.NumConstraints() - 1)) += Adense * Einv_Frd_rc;

    // TODO(stephentu): use a more efficient method (e.g. LU decomposition)
    //std::cout << "rhs" << std::endl;
    //std::cout << rhs << std::endl;

    arma::solve(dy, M, rhs);
    if (sdp.NumSparseConstraints())
      dysparse = dy(arma::span(0, sdp.NumSparseConstraints() - 1));
    if (sdp.NumDenseConstraints())
      dydense = dy(arma::span(sdp.NumSparseConstraints(), sdp.NumConstraints() - 1));
    //std::cout << "dy" << std::endl;
    //std::cout << dy << std::endl;

    math::Smat(F * (rd - Asparse.t() * dysparse - Adense.t() * dydense) - rc, Frd_ATdy_rc_Mat);
    SolveLyapunov(Einv_Frd_ATdy_rc_Mat, Z, 2. * Frd_ATdy_rc_Mat);
    math::Svec(Einv_Frd_ATdy_rc_Mat, Einv_Frd_ATdy_rc);
    dsx = -Einv_Frd_ATdy_rc;

    //std::cout << "dsx" << std::endl;
    //std::cout << dsx << std::endl;

    dsz = rd - Asparse.t() * dysparse - Adense.t() * dydense;

    //std::cout << "dsz" << std::endl;
    //std::cout << dsz << std::endl;

    math::Smat(dsx, dX);
    math::Smat(dsz, dZ);

    double alphahatX = AlphaHat(X, dX);
    if (alphahatX < 0.)
      // dX is PSD
      alphahatX = 1.;

    double alphahatZ = AlphaHat(Z, dZ);
    if (alphahatZ < 0.)
      // dZ is PSD
      alphahatZ = 1.;

    const double alpha = std::min(1., tau * alphahatX);
    const double beta = std::min(1., tau * alphahatZ);

    X += alpha * dX;
    math::Svec(X, sx);
    ysparse += beta * dysparse;
    ydense += beta * dydense;
    Z += beta * dZ;
    math::Svec(Z, sz);

    const double norm_XZ = arma::norm(X * Z, "fro");

    const double sparse_primal_infeas = arma::norm(sdp.SparseB() - Asparse * sx, 2);
    const double dense_primal_infeas = arma::norm(sdp.DenseB() - Adense * sx, 2);
    const double primal_infeas = sqrt(
        sparse_primal_infeas * sparse_primal_infeas +
        dense_primal_infeas * dense_primal_infeas);

    double primal_obj = 0.;
    if (sdp.HasSparseObjective())
      primal_obj += arma::dot(sdp.SparseC(), X);
    if (sdp.HasDenseObjective())
      primal_obj += arma::dot(sdp.DenseC(), X);

    const double dual_obj =
      arma::dot(sdp.SparseB(), ysparse) +
      arma::dot(sdp.DenseB(), ydense);

    const double duality_gap = primal_obj - dual_obj;

    DualCheck = Z;
    if (sdp.HasSparseObjective())
      DualCheck -= sdp.SparseC();
    if (sdp.HasDenseObjective())
      DualCheck -= sdp.DenseC();
    for (size_t i = 0; i < sdp.NumSparseConstraints(); i++)
      DualCheck += ysparse(i) * sdp.SparseA()[i];
    for (size_t i = 0; i < sdp.NumDenseConstraints(); i++)
      DualCheck += ydense(i) * sdp.DenseA()[i];
    const double dual_infeas = arma::norm(DualCheck, "fro");

    Log::Debug
      << "iter=" << iteration + 1 << ", "
      << "primal=" << primal_obj << ", "
      << "dual=" << dual_obj << ", "
      << "gap=" << duality_gap << ", "
      << "||XZ||=" << norm_XZ << ", "
      << "primal_infeas=" << primal_infeas << ", "
      << "dual_infeas=" << dual_infeas << ", "
      << "mu=" << mu
      << std::endl;

    if (norm_XZ <= normXzTol &&
        primal_infeas <= primalInfeasTol &&
        dual_infeas <= dualInfeasTol)
      return primal_obj;
  }

  Log::Warn << "did not converge" << std::endl;
  return -1;
}

} // namespace optimization
} // namespace mlpack
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <string>

#include "version.h"

// Name of client reported in the 'version' message. Report the same name
// for both bitcoind and bitcoin-qt, to make it harder for attackers to
// target servers or GUI users specifically.
const std::string CLIENT_NAME("Satoshi");

// Client version number
#ifdef NEBLIO_REST
#define CLIENT_VERSION_SUFFIX   "-REST-Enabled"
#else
#define CLIENT_VERSION_SUFFIX   "-RC1"
#endif

// The following part of the code determines the CLIENT_BUILD variable.
// Several mechanisms are used for this:
// * first, if HAVE_BUILD_INFO is defined, include build.h, a file that is
//   generated by the build environment, possibly containing the output
//   of git-describe in a macro called BUILD_DESC
// * secondly, if this is an exported version of the code, GIT_ARCHIVE will
//   be defined (automatically using the export-subst git attribute), and
//   GIT_COMMIT will contain the commit id.
// * then, three options exist for determining CLIENT_BUILD:
//   * if BUILD_DESC is defined, use that literally (output of git-describe)
//   * if not, but GIT_COMMIT is defined, use v[maj].[min].[rev].[build]-g[commit]
//   * otherwise, use v[maj].[min].[rev].[build]-unk
// finally CLIENT_VERSION_SUFFIX is added

// First, include build.h if requested
#ifdef HAVE_BUILD_INFO
#    include "build.h"
#endif

// git will put "#define GIT_ARCHIVE 1" on the next line inside archives.
#define GIT_ARCHIVE 0
#ifdef GIT_ARCHIVE
#    define GIT_COMMIT_ID ""
#    define GIT_COMMIT_DATE "$Format:%cD"
#endif

#define BUILD_DESC_FROM_COMMIT(maj,min,rev,build,commit) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "" commit

#define BUILD_DESC_FROM_UNKNOWN(maj,min,rev,build) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-unk"

#ifndef BUILD_DESC
#    ifdef GIT_COMMIT_ID
#        define BUILD_DESC BUILD_DESC_FROM_COMMIT(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD, GIT_COMMIT_ID)
#    else
#        define BUILD_DESC BUILD_DESC_FROM_UNKNOWN(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD)
#    endif
#endif

#ifndef BUILD_DATE
#    ifdef GIT_COMMIT_DATE
#        define BUILD_DATE GIT_COMMIT_DATE
#    else
#        define BUILD_DATE __DATE__ ", " __TIME__
#    endif
#endif

const std::string CLIENT_BUILD(BUILD_DESC CLIENT_VERSION_SUFFIX);
const std::string CLIENT_DATE(BUILD_DATE);
<commit_msg>Remove RC1 Suffix<commit_after>// Copyright (c) 2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <string>

#include "version.h"

// Name of client reported in the 'version' message. Report the same name
// for both bitcoind and bitcoin-qt, to make it harder for attackers to
// target servers or GUI users specifically.
const std::string CLIENT_NAME("Satoshi");

// Client version number
#ifdef NEBLIO_REST
#define CLIENT_VERSION_SUFFIX   "-REST-Enabled"
#else
#define CLIENT_VERSION_SUFFIX   ""
#endif

// The following part of the code determines the CLIENT_BUILD variable.
// Several mechanisms are used for this:
// * first, if HAVE_BUILD_INFO is defined, include build.h, a file that is
//   generated by the build environment, possibly containing the output
//   of git-describe in a macro called BUILD_DESC
// * secondly, if this is an exported version of the code, GIT_ARCHIVE will
//   be defined (automatically using the export-subst git attribute), and
//   GIT_COMMIT will contain the commit id.
// * then, three options exist for determining CLIENT_BUILD:
//   * if BUILD_DESC is defined, use that literally (output of git-describe)
//   * if not, but GIT_COMMIT is defined, use v[maj].[min].[rev].[build]-g[commit]
//   * otherwise, use v[maj].[min].[rev].[build]-unk
// finally CLIENT_VERSION_SUFFIX is added

// First, include build.h if requested
#ifdef HAVE_BUILD_INFO
#    include "build.h"
#endif

// git will put "#define GIT_ARCHIVE 1" on the next line inside archives.
#define GIT_ARCHIVE 0
#ifdef GIT_ARCHIVE
#    define GIT_COMMIT_ID ""
#    define GIT_COMMIT_DATE "$Format:%cD"
#endif

#define BUILD_DESC_FROM_COMMIT(maj,min,rev,build,commit) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "" commit

#define BUILD_DESC_FROM_UNKNOWN(maj,min,rev,build) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-unk"

#ifndef BUILD_DESC
#    ifdef GIT_COMMIT_ID
#        define BUILD_DESC BUILD_DESC_FROM_COMMIT(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD, GIT_COMMIT_ID)
#    else
#        define BUILD_DESC BUILD_DESC_FROM_UNKNOWN(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD)
#    endif
#endif

#ifndef BUILD_DATE
#    ifdef GIT_COMMIT_DATE
#        define BUILD_DATE GIT_COMMIT_DATE
#    else
#        define BUILD_DATE __DATE__ ", " __TIME__
#    endif
#endif

const std::string CLIENT_BUILD(BUILD_DESC CLIENT_VERSION_SUFFIX);
const std::string CLIENT_DATE(BUILD_DATE);
<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

// this one has to come first
#include <dune/stuff/test/main.hxx>

#include "spaces_fv_default.hh"
#include "spaces_dg_fem.hh"

#include "products_weightedl2.hh"

typedef testing::Types< SPACE_FV_SGRID(1, 1)
                      , SPACE_FV_SGRID(2, 1)
                      , SPACE_FV_SGRID(3, 1)
                      > ConstantSpaces;

TYPED_TEST_CASE(WeightedL2LocalizableProduct, ConstantSpaces);
TYPED_TEST(WeightedL2LocalizableProduct, fulfills_interface) {
  this->fulfills_interface();
}
TYPED_TEST(WeightedL2LocalizableProduct, constant_arguments) {
  this->constant_arguments();
}
TYPED_TEST(WeightedL2LocalizableProduct, linear_arguments) {
  this->linear_arguments();
}
TYPED_TEST(WeightedL2LocalizableProduct, quadratic_arguments) {
  this->quadratic_arguments();
}

#if HAVE_DUNE_FEM

typedef testing::Types<
                        SPACE_DG_FEM_SGRID(1, 1, 2)
                      , SPACE_DG_FEM_SGRID(2, 1, 2)
                      , SPACE_DG_FEM_SGRID(3, 1, 2)
                      > QuadraticSpaces;

TYPED_TEST_CASE(WeightedL2AssemblableProduct, QuadraticSpaces);
TYPED_TEST(WeightedL2AssemblableProduct, fulfills_interface) {
  this->fulfills_interface();
}
TYPED_TEST(WeightedL2AssemblableProduct, constant_arguments) {
  this->constant_arguments();
}
TYPED_TEST(WeightedL2AssemblableProduct, linear_arguments) {
  this->linear_arguments();
}
TYPED_TEST(WeightedL2AssemblableProduct, quadratic_arguments) {
  this->quadratic_arguments();
}

#else // HAVE_DUNE_FEM

TYPED_TEST_CASE(WeightedL2AssemblableProduct, ConstantSpaces);
TYPED_TEST(WeightedL2AssemblableProduct, fulfills_interface) {
  this->fulfills_interface();
}
TYPED_TEST(WeightedL2AssemblableProduct, constant_arguments) {
  this->constant_arguments();
}
TEST(DISABLED_WeightedL2AssemblableProduct, linear_arguments)    {}
TEST(DISABLED_WeightedL2AssemblableProduct, quadratic_arguments) {}

#endif // HAVE_DUNE_FEM

TYPED_TEST_CASE(WeightedL2Product, ConstantSpaces);
TYPED_TEST(WeightedL2Product, fulfills_interface) {
  this->fulfills_interface();
}
TYPED_TEST(WeightedL2Product, constant_arguments) {
  this->constant_arguments();
}
TYPED_TEST(WeightedL2Product, linear_arguments) {
  this->linear_arguments();
}
TYPED_TEST(WeightedL2Product, quadratic_arguments) {
  this->quadratic_arguments();
}

<commit_msg>[test.products_weightedl2] whitespace<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

// this one has to come first
#include <dune/stuff/test/main.hxx>

#include "spaces_fv_default.hh"
#include "spaces_dg_fem.hh"

#include "products_weightedl2.hh"

typedef testing::Types< SPACE_FV_SGRID(1, 1)
                      , SPACE_FV_SGRID(2, 1)
                      , SPACE_FV_SGRID(3, 1)
                      > ConstantSpaces;

TYPED_TEST_CASE(WeightedL2LocalizableProduct, ConstantSpaces);
TYPED_TEST(WeightedL2LocalizableProduct, fulfills_interface) {
  this->fulfills_interface();
}
TYPED_TEST(WeightedL2LocalizableProduct, constant_arguments) {
  this->constant_arguments();
}
TYPED_TEST(WeightedL2LocalizableProduct, linear_arguments) {
  this->linear_arguments();
}
TYPED_TEST(WeightedL2LocalizableProduct, quadratic_arguments) {
  this->quadratic_arguments();
}

#if HAVE_DUNE_FEM

typedef testing::Types<
                        SPACE_DG_FEM_SGRID(1, 1, 2)
                      , SPACE_DG_FEM_SGRID(2, 1, 2)
                      , SPACE_DG_FEM_SGRID(3, 1, 2)
                      > QuadraticSpaces;

TYPED_TEST_CASE(WeightedL2AssemblableProduct, QuadraticSpaces);
TYPED_TEST(WeightedL2AssemblableProduct, fulfills_interface) {
  this->fulfills_interface();
}
TYPED_TEST(WeightedL2AssemblableProduct, constant_arguments) {
  this->constant_arguments();
}
TYPED_TEST(WeightedL2AssemblableProduct, linear_arguments) {
  this->linear_arguments();
}
TYPED_TEST(WeightedL2AssemblableProduct, quadratic_arguments) {
  this->quadratic_arguments();
}

#else // HAVE_DUNE_FEM

TYPED_TEST_CASE(WeightedL2AssemblableProduct, ConstantSpaces);
TYPED_TEST(WeightedL2AssemblableProduct, fulfills_interface) {
  this->fulfills_interface();
}
TYPED_TEST(WeightedL2AssemblableProduct, constant_arguments) {
  this->constant_arguments();
}
TEST(DISABLED_WeightedL2AssemblableProduct, linear_arguments)    {}
TEST(DISABLED_WeightedL2AssemblableProduct, quadratic_arguments) {}

#endif // HAVE_DUNE_FEM

TYPED_TEST_CASE(WeightedL2Product, ConstantSpaces);
TYPED_TEST(WeightedL2Product, fulfills_interface) {
  this->fulfills_interface();
}
TYPED_TEST(WeightedL2Product, constant_arguments) {
  this->constant_arguments();
}
TYPED_TEST(WeightedL2Product, linear_arguments) {
  this->linear_arguments();
}
TYPED_TEST(WeightedL2Product, quadratic_arguments) {
  this->quadratic_arguments();
}
<|endoftext|>


<commit_before>/*
 * This file is part of the UnTech Editor Suite.
 * Copyright (c) 2016 - 2021, Marcus Rowe <undisbeliever@gmail.com>.
 * Distributed under The MIT License: https://opensource.org/licenses/MIT
 */

#include "romtiledata.h"
#include <algorithm>
#include <iomanip>

using namespace UnTech::MetaSprite::Compiler;
<commit_msg>Remove unused file romtiledata.cpp<commit_after><|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (c) 2017 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file mavlink_command_sender.cpp
 * Mavlink commands sender with support for retransmission.
 *
 * @author Julian Oes <julian@oes.ch>
 */

#include "mavlink_command_sender.h"
#include <px4_log.h>

#define CMD_DEBUG(FMT, ...) PX4_LOG_NAMED_COND("cmd sender", _debug_enabled, FMT, ##__VA_ARGS__)

MavlinkCommandSender *MavlinkCommandSender::_instance = nullptr;
px4_sem_t MavlinkCommandSender::_lock;

void MavlinkCommandSender::initialize()
{
	px4_sem_init(&_lock, 1, 1);

	if (_instance == nullptr) {
		_instance = new MavlinkCommandSender();
	}
}

MavlinkCommandSender &MavlinkCommandSender::instance()
{
	return *_instance;
}

MavlinkCommandSender::~MavlinkCommandSender()
{
	px4_sem_destroy(&_lock);
}

int MavlinkCommandSender::handle_vehicle_command(const struct vehicle_command_s &command, mavlink_channel_t channel)
{
	lock();
	CMD_DEBUG("new command: %d (channel: %d)", command.command, channel);

	mavlink_command_long_t msg = {};
	msg.target_system = command.target_system;
	msg.target_component = command.target_component;
	msg.command = command.command;
	msg.confirmation = command.confirmation;
	msg.param1 = command.param1;
	msg.param2 = command.param2;
	msg.param3 = command.param3;
	msg.param4 = command.param4;
	msg.param5 = command.param5;
	msg.param6 = command.param6;
	msg.param7 = command.param7;
	mavlink_msg_command_long_send_struct(channel, &msg);

	bool already_existing = false;
	_commands.reset_to_start();

	while (command_item_t *item = _commands.get_next()) {
		if (item->timestamp_us == command.timestamp) {

			// We should activate the channel by setting num_sent_per_channel from -1 to 0.
			item->num_sent_per_channel[channel] = 0;
			already_existing = true;
			break;
		}
	}

	if (!already_existing) {

		command_item_t new_item;
		new_item.command = msg;
		new_item.timestamp_us = command.timestamp;
		new_item.num_sent_per_channel[channel] = 0;
		new_item.last_time_sent_us = hrt_absolute_time();
		_commands.put(new_item);
	}

	unlock();
	return 0;
}

void MavlinkCommandSender::handle_mavlink_command_ack(const mavlink_command_ack_t &ack,
		uint8_t from_sysid, uint8_t from_compid, uint8_t channel)
{
	CMD_DEBUG("handling result %d for command %d (from %d:%d)",
		  ack.result, ack.command, from_sysid, from_compid);
	lock();

	_commands.reset_to_start();

	while (command_item_t *item = _commands.get_next()) {
		// Check if the incoming ack matches any of the commands that we have sent.
		if (item->command.command == ack.command &&
		    from_sysid == item->command.target_system &&
		    from_compid == item->command.target_component &&
		    item->num_sent_per_channel[channel] != -1) {
			item->num_sent_per_channel[channel] = -2;	// mark this as acknowledged
			break;
		}
	}

	unlock();
}

void MavlinkCommandSender::check_timeout(mavlink_channel_t channel)
{
	lock();

	_commands.reset_to_start();

	while (command_item_t *item = _commands.get_next()) {
		if (hrt_elapsed_time(&item->last_time_sent_us) <= TIMEOUT_US) {
			// We keep waiting for the timeout.
			continue;
		}

		// Loop through num_sent_per_channel and check if any channel has receives an ack for this command
		// (indicated by the value -2). We avoid removing the command at the time of receiving the ack
		// as some channels might be lagging behind and will end up putting the same command into the buffer.
		bool dropped_command = false;

		for (unsigned i = 0; i < MAX_MAVLINK_CHANNEL; ++i) {
			if (item->num_sent_per_channel[i] == -2) {
				_commands.drop_current();
				dropped_command = true;
				break;
			}
		}

		if (dropped_command) {
			continue;
		}

		// The goal of this is to retry from all channels. Therefore, we keep
		// track of the retry count for each channel.
		//
		// When the first channel does a retry, the timeout is reset.
		// (e.g. all channel have done 2 retries, then channel 0 is called
		// and does retry number 3, and also resets the timeout timestamp).

		// First, we need to determine what the current max and min retry level
		// are because we can only level up, if all have caught up.
		// If num_sent_per_channel is at -1, the channel is inactive.
		int8_t max_sent = 0;
		int8_t min_sent = INT8_MAX;

		for (unsigned i = 0; i < MAX_MAVLINK_CHANNEL; ++i) {
			if (item->num_sent_per_channel[i] > max_sent) {
				max_sent = item->num_sent_per_channel[i];
			}

			if ((item->num_sent_per_channel[i] != -1) &&
			    (item->num_sent_per_channel[i] < min_sent)) {
				min_sent = item->num_sent_per_channel[i];
			}
		}

		if (item->num_sent_per_channel[channel] < max_sent && item->num_sent_per_channel[channel] != -1) {
			// We are behind and need to do a retransmission.
			mavlink_msg_command_long_send_struct(channel, &item->command);
			item->num_sent_per_channel[channel]++;

			CMD_DEBUG("command %d sent (not first, retries: %d/%d, channel: %d)",
				  item->command.command,
				  item->num_sent_per_channel[channel],
				  max_sent,
				  channel);

		} else if (item->num_sent_per_channel[channel] == max_sent &&
			   min_sent == max_sent) {

			// If the next retry would be above the needed retries anyway, we can
			// drop the item, and continue with other items.
			if (item->num_sent_per_channel[channel] + 1 > RETRIES) {
				CMD_DEBUG("command %d dropped", item->command.command);
				_commands.drop_current();
				continue;
			}

			// We are the first of a new retransmission series.
			mavlink_msg_command_long_send_struct(channel, &item->command);
			item->num_sent_per_channel[channel]++;
			// Therefore, we are the ones setting the timestamp of this retry round.
			item->last_time_sent_us = hrt_absolute_time();

			CMD_DEBUG("command %d sent (first, retries: %d/%d, channel: %d)",
				  item->command.command,
				  item->num_sent_per_channel[channel],
				  max_sent,
				  channel);

		} else {
			// We are already ahead, so this should not happen.
			// If it ever does, just ignore it. It will timeout eventually.
			continue;
		}
	}

	unlock();
}
<commit_msg>mavlink: match commands aimed at any sysid/compid<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2017 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file mavlink_command_sender.cpp
 * Mavlink commands sender with support for retransmission.
 *
 * @author Julian Oes <julian@oes.ch>
 */

#include "mavlink_command_sender.h"
#include <px4_log.h>

#define CMD_DEBUG(FMT, ...) PX4_LOG_NAMED_COND("cmd sender", _debug_enabled, FMT, ##__VA_ARGS__)

MavlinkCommandSender *MavlinkCommandSender::_instance = nullptr;
px4_sem_t MavlinkCommandSender::_lock;

void MavlinkCommandSender::initialize()
{
	px4_sem_init(&_lock, 1, 1);

	if (_instance == nullptr) {
		_instance = new MavlinkCommandSender();
	}
}

MavlinkCommandSender &MavlinkCommandSender::instance()
{
	return *_instance;
}

MavlinkCommandSender::~MavlinkCommandSender()
{
	px4_sem_destroy(&_lock);
}

int MavlinkCommandSender::handle_vehicle_command(const struct vehicle_command_s &command, mavlink_channel_t channel)
{
	lock();
	CMD_DEBUG("new command: %d (channel: %d)", command.command, channel);

	mavlink_command_long_t msg = {};
	msg.target_system = command.target_system;
	msg.target_component = command.target_component;
	msg.command = command.command;
	msg.confirmation = command.confirmation;
	msg.param1 = command.param1;
	msg.param2 = command.param2;
	msg.param3 = command.param3;
	msg.param4 = command.param4;
	msg.param5 = command.param5;
	msg.param6 = command.param6;
	msg.param7 = command.param7;
	mavlink_msg_command_long_send_struct(channel, &msg);

	bool already_existing = false;
	_commands.reset_to_start();

	while (command_item_t *item = _commands.get_next()) {
		if (item->timestamp_us == command.timestamp) {

			// We should activate the channel by setting num_sent_per_channel from -1 to 0.
			item->num_sent_per_channel[channel] = 0;
			already_existing = true;
			break;
		}
	}

	if (!already_existing) {

		command_item_t new_item;
		new_item.command = msg;
		new_item.timestamp_us = command.timestamp;
		new_item.num_sent_per_channel[channel] = 0;
		new_item.last_time_sent_us = hrt_absolute_time();
		_commands.put(new_item);
	}

	unlock();
	return 0;
}

void MavlinkCommandSender::handle_mavlink_command_ack(const mavlink_command_ack_t &ack,
		uint8_t from_sysid, uint8_t from_compid, uint8_t channel)
{
	CMD_DEBUG("handling result %d for command %d (from %d:%d)",
		  ack.result, ack.command, from_sysid, from_compid);
	lock();

	_commands.reset_to_start();

	while (command_item_t *item = _commands.get_next()) {
		// Check if the incoming ack matches any of the commands that we have sent.
		if (item->command.command == ack.command &&
		    (item->command.target_system == 0 || from_sysid == item->command.target_system) &&
		    (item->command.target_component == 0 || from_compid == item->command.target_component) &&
		    item->num_sent_per_channel[channel] != -1) {
			item->num_sent_per_channel[channel] = -2;	// mark this as acknowledged
			break;
		}
	}

	unlock();
}

void MavlinkCommandSender::check_timeout(mavlink_channel_t channel)
{
	lock();

	_commands.reset_to_start();

	while (command_item_t *item = _commands.get_next()) {
		if (hrt_elapsed_time(&item->last_time_sent_us) <= TIMEOUT_US) {
			// We keep waiting for the timeout.
			continue;
		}

		// Loop through num_sent_per_channel and check if any channel has receives an ack for this command
		// (indicated by the value -2). We avoid removing the command at the time of receiving the ack
		// as some channels might be lagging behind and will end up putting the same command into the buffer.
		bool dropped_command = false;

		for (unsigned i = 0; i < MAX_MAVLINK_CHANNEL; ++i) {
			if (item->num_sent_per_channel[i] == -2) {
				_commands.drop_current();
				dropped_command = true;
				break;
			}
		}

		if (dropped_command) {
			continue;
		}

		// The goal of this is to retry from all channels. Therefore, we keep
		// track of the retry count for each channel.
		//
		// When the first channel does a retry, the timeout is reset.
		// (e.g. all channel have done 2 retries, then channel 0 is called
		// and does retry number 3, and also resets the timeout timestamp).

		// First, we need to determine what the current max and min retry level
		// are because we can only level up, if all have caught up.
		// If num_sent_per_channel is at -1, the channel is inactive.
		int8_t max_sent = 0;
		int8_t min_sent = INT8_MAX;

		for (unsigned i = 0; i < MAX_MAVLINK_CHANNEL; ++i) {
			if (item->num_sent_per_channel[i] > max_sent) {
				max_sent = item->num_sent_per_channel[i];
			}

			if ((item->num_sent_per_channel[i] != -1) &&
			    (item->num_sent_per_channel[i] < min_sent)) {
				min_sent = item->num_sent_per_channel[i];
			}
		}

		if (item->num_sent_per_channel[channel] < max_sent && item->num_sent_per_channel[channel] != -1) {
			// We are behind and need to do a retransmission.
			mavlink_msg_command_long_send_struct(channel, &item->command);
			item->num_sent_per_channel[channel]++;

			CMD_DEBUG("command %d sent (not first, retries: %d/%d, channel: %d)",
				  item->command.command,
				  item->num_sent_per_channel[channel],
				  max_sent,
				  channel);

		} else if (item->num_sent_per_channel[channel] == max_sent &&
			   min_sent == max_sent) {

			// If the next retry would be above the needed retries anyway, we can
			// drop the item, and continue with other items.
			if (item->num_sent_per_channel[channel] + 1 > RETRIES) {
				CMD_DEBUG("command %d dropped", item->command.command);
				_commands.drop_current();
				continue;
			}

			// We are the first of a new retransmission series.
			mavlink_msg_command_long_send_struct(channel, &item->command);
			item->num_sent_per_channel[channel]++;
			// Therefore, we are the ones setting the timestamp of this retry round.
			item->last_time_sent_us = hrt_absolute_time();

			CMD_DEBUG("command %d sent (first, retries: %d/%d, channel: %d)",
				  item->command.command,
				  item->num_sent_per_channel[channel],
				  max_sent,
				  channel);

		} else {
			// We are already ahead, so this should not happen.
			// If it ever does, just ignore it. It will timeout eventually.
			continue;
		}
	}

	unlock();
}
<|endoftext|>