<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2009 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id$

#ifndef MAPNIK_EXPRESSIONS_GRAMMAR_HPP
#define MAPNIK_EXPRESSIONS_GRAMMAR_HPP

// mapnik
#include <mapnik/value.hpp>
#include <mapnik/expression_node.hpp>

// boost
#include <boost/version.hpp>
#include <boost/variant.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/concept_check.hpp>
//spirit2
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_action.hpp>
//fusion
#include <boost/fusion/include/adapt_struct.hpp>
//phoenix
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_function.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/home/phoenix/object/construct.hpp>

namespace mapnik
{

namespace qi = boost::spirit::qi;
namespace standard_wide =  boost::spirit::standard_wide;
using standard_wide::space_type;

struct unicode_impl
{
    template <typename T>
    struct result
    {
        typedef UnicodeString type;
    };

    explicit unicode_impl(mapnik::transcoder const& tr)
        : tr_(tr) {}

    UnicodeString operator()(std::string const& str) const
    {
        return tr_.transcode(str.c_str());
    }

    mapnik::transcoder const& tr_;
};

struct regex_match_impl
{
    template <typename T0, typename T1>
    struct result
    {
        typedef expr_node type;
    };

    explicit regex_match_impl(mapnik::transcoder const& tr)
        : tr_(tr) {}

    template <typename T0,typename T1>
    expr_node operator() (T0 & node, T1 const& pattern) const
    {
        return regex_match_node(node,tr_.transcode(pattern.c_str()));
    }

    mapnik::transcoder const& tr_;
};

struct regex_replace_impl
{
    template <typename T0, typename T1, typename T2>
    struct result
    {
        typedef expr_node type;
    };

    explicit regex_replace_impl(mapnik::transcoder const& tr)
        : tr_(tr) {}

    template <typename T0,typename T1,typename T2>
    expr_node operator() (T0 & node, T1 const& pattern, T2 const& format) const
    {
        return regex_replace_node(node,tr_.transcode(pattern.c_str()),tr_.transcode(format.c_str()));
    }

    mapnik::transcoder const& tr_;
};

template <typename Iterator>
struct expression_grammar : qi::grammar<Iterator, expr_node(), space_type>
{
    typedef qi::rule<Iterator, expr_node(), space_type> rule_type;

    explicit expression_grammar(mapnik::transcoder const& tr)
        : expression_grammar::base_type(expr),
          unicode_(unicode_impl(tr)),
          regex_match_(regex_match_impl(tr)),
          regex_replace_(regex_replace_impl(tr))
    {
        using boost::phoenix::construct;
        using qi::_1;
        using qi::_a;
        using qi::_b;
        using qi::_r1;
#if BOOST_VERSION > 104200
        using qi::no_skip;
#else
        using qi::lexeme;
#endif
        using qi::_val;
        using qi::lit;
        using qi::int_;
        using qi::double_;
        using standard_wide::char_;

        expr = logical_expr.alias();

        logical_expr = not_expr [_val = _1]
            >>
            *(  (  ( lit("and") | lit("&&")) >> not_expr [_val && _1] )
                | (( lit("or") | lit("||")) >> not_expr [_val || _1])
                )
            ;

        not_expr =
            cond_expr [_val = _1 ]
            | ((lit("not") | lit('!')) >> cond_expr [ _val = !_1 ])
            ;

        cond_expr = equality_expr [_val = _1] | additive_expr [_val = _1]
            ;

        equality_expr =
            relational_expr [_val = _1]
            >> *(  ( (lit("=") | lit("eq")) >> relational_expr [_val == _1])
                   | (( lit("!=") | lit("<>") | lit("neq") ) >> relational_expr [_val != _1])
                )
            ;

        regex_match_expr = lit(".match")
            >> lit('(')
            >> lit('\'')
            >> ustring [_val = _1]
            >> lit('\'')
            >> lit(')')
            ;

        regex_replace_expr =
            lit(".replace")
            >> lit('(')
            >> lit('\'')
            >> ustring           [_a = _1]
            >> lit('\'') >> lit(',')
            >> lit('\'')
            >> ustring           [_b = _1]
            >> lit('\'')
            >> lit(')')          [_val = regex_replace_(_r1,_a,_b)]
            ;

        relational_expr = additive_expr[_val = _1]
            >>
            *(  (   (lit("<=") | lit("le") ) >> additive_expr [ _val <= _1 ])
                | ( (lit('<')  | lit("lt") ) >> additive_expr [ _val <  _1 ])
                | ( (lit(">=") | lit("ge") ) >> additive_expr [ _val >= _1 ])
                | ( (lit('>')  | lit("gt") ) >> additive_expr [ _val >  _1 ])
                )
            ;
        additive_expr = multiplicative_expr [_val = _1]
            >> * (   '+' >> multiplicative_expr[_val += _1]
                     | '-' >> multiplicative_expr[_val -= _1]
                )
            ;

        multiplicative_expr = primary_expr [_val = _1]
            >> *(     '*' >> primary_expr [_val *= _1]
                      | '/' >> primary_expr [_val /= _1]
                      | '%' >> primary_expr [_val %= _1]
                      |  regex_match_expr[_val = regex_match_(_val, _1)]
                      |  regex_replace_expr(_val) [_val = _1]
                )
            ;

        primary_expr = strict_double [_val = _1]
            | int_ [_val = _1]
            | lit("true") [_val = true]
            | lit("false") [_val = false]
            | ustring [_val = unicode_(_1) ]
            | attr [_val = construct<attribute>( _1 ) ]
            | '(' >> expr [_val = _1 ] >> ')'
            ;

        attr %= '[' >> +(char_ - ']') >> ']';
#if BOOST_VERSION > 104200
        ustring %= '\'' >> no_skip[*~char_('\'')] >> '\'';
#else
        ustring %= '\'' >> lexeme[*(char_-'\'')] >> '\'';
#endif
    }

    qi::real_parser<double, qi::strict_real_policies<double> > strict_double;
    boost::phoenix::function<unicode_impl> unicode_;
    boost::phoenix::function<regex_match_impl> regex_match_;
    boost::phoenix::function<regex_replace_impl> regex_replace_;
    //
    rule_type expr;
    rule_type equality_expr;
    rule_type cond_expr;
    rule_type relational_expr;
    rule_type logical_expr;
    rule_type additive_expr;
    rule_type multiplicative_expr;
    rule_type not_expr;
    rule_type primary_expr;
    qi::rule<Iterator, std::string() > regex_match_expr;
    qi::rule<Iterator, expr_node(expr_node), qi::locals<std::string,std::string>, space_type> regex_replace_expr;
    qi::rule<Iterator, std::string() , space_type> attr;
    qi::rule<Iterator, std::string() > ustring;
};

} // namespace

#endif  // MAPNIK_EXPRESSIONS_GRAMMAR_HPP
<commit_msg>+ fixed bug introduced in r1920   (ustring parser includes single quotes    - remove extra '\'' in match/replace)<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2009 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id$

#ifndef MAPNIK_EXPRESSIONS_GRAMMAR_HPP
#define MAPNIK_EXPRESSIONS_GRAMMAR_HPP

// mapnik
#include <mapnik/value.hpp>
#include <mapnik/expression_node.hpp>

// boost
#include <boost/version.hpp>
#include <boost/variant.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/concept_check.hpp>
//spirit2
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_action.hpp>
//fusion
#include <boost/fusion/include/adapt_struct.hpp>
//phoenix
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_function.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/home/phoenix/object/construct.hpp>

namespace mapnik
{

namespace qi = boost::spirit::qi;
namespace standard_wide =  boost::spirit::standard_wide;
using standard_wide::space_type;

struct unicode_impl
{
    template <typename T>
    struct result
    {
        typedef UnicodeString type;
    };

    explicit unicode_impl(mapnik::transcoder const& tr)
        : tr_(tr) {}

    UnicodeString operator()(std::string const& str) const
    {
        return tr_.transcode(str.c_str());
    }

    mapnik::transcoder const& tr_;
};

struct regex_match_impl
{
    template <typename T0, typename T1>
    struct result
    {
        typedef expr_node type;
    };

    explicit regex_match_impl(mapnik::transcoder const& tr)
        : tr_(tr) {}

    template <typename T0,typename T1>
    expr_node operator() (T0 & node, T1 const& pattern) const
    {
        return regex_match_node(node,tr_.transcode(pattern.c_str()));
    }

    mapnik::transcoder const& tr_;
};

struct regex_replace_impl
{
    template <typename T0, typename T1, typename T2>
    struct result
    {
        typedef expr_node type;
    };

    explicit regex_replace_impl(mapnik::transcoder const& tr)
        : tr_(tr) {}

    template <typename T0,typename T1,typename T2>
    expr_node operator() (T0 & node, T1 const& pattern, T2 const& format) const
    {
        return regex_replace_node(node,tr_.transcode(pattern.c_str()),tr_.transcode(format.c_str()));
    }

    mapnik::transcoder const& tr_;
};

template <typename Iterator>
struct expression_grammar : qi::grammar<Iterator, expr_node(), space_type>
{
    typedef qi::rule<Iterator, expr_node(), space_type> rule_type;

    explicit expression_grammar(mapnik::transcoder const& tr)
        : expression_grammar::base_type(expr),
          unicode_(unicode_impl(tr)),
          regex_match_(regex_match_impl(tr)),
          regex_replace_(regex_replace_impl(tr))
    {
        using boost::phoenix::construct;
        using qi::_1;
        using qi::_a;
        using qi::_b;
        using qi::_r1;
#if BOOST_VERSION > 104200
        using qi::no_skip;
#else
        using qi::lexeme;
#endif
        using qi::_val;
        using qi::lit;
        using qi::int_;
        using qi::double_;
        using standard_wide::char_;

        expr = logical_expr.alias();

        logical_expr = not_expr [_val = _1]
            >>
            *(  (  ( lit("and") | lit("&&")) >> not_expr [_val && _1] )
                | (( lit("or") | lit("||")) >> not_expr [_val || _1])
                )
            ;

        not_expr =
            cond_expr [_val = _1 ]
            | ((lit("not") | lit('!')) >> cond_expr [ _val = !_1 ])
            ;

        cond_expr = equality_expr [_val = _1] | additive_expr [_val = _1]
            ;

        equality_expr =
            relational_expr [_val = _1]
            >> *(  ( (lit("=") | lit("eq")) >> relational_expr [_val == _1])
                   | (( lit("!=") | lit("<>") | lit("neq") ) >> relational_expr [_val != _1])
                )
            ;

        regex_match_expr = lit(".match")
            >> lit('(')
            >> ustring [_val = _1]
            >> lit(')')
            ;

        regex_replace_expr =
            lit(".replace")
            >> lit('(')
            >> ustring           [_a = _1]
            >> lit(',')
            >> ustring           [_b = _1]
            >> lit(')')          [_val = regex_replace_(_r1,_a,_b)]
            ;

        relational_expr = additive_expr[_val = _1]
            >>
            *(  (   (lit("<=") | lit("le") ) >> additive_expr [ _val <= _1 ])
                | ( (lit('<')  | lit("lt") ) >> additive_expr [ _val <  _1 ])
                | ( (lit(">=") | lit("ge") ) >> additive_expr [ _val >= _1 ])
                | ( (lit('>')  | lit("gt") ) >> additive_expr [ _val >  _1 ])
                )
            ;
        additive_expr = multiplicative_expr [_val = _1]
            >> * (   '+' >> multiplicative_expr[_val += _1]
                     | '-' >> multiplicative_expr[_val -= _1]
                )
            ;

        multiplicative_expr = primary_expr [_val = _1]
            >> *(     '*' >> primary_expr [_val *= _1]
                      | '/' >> primary_expr [_val /= _1]
                      | '%' >> primary_expr [_val %= _1]
                      |  regex_match_expr[_val = regex_match_(_val, _1)]
                      |  regex_replace_expr(_val) [_val = _1]
                )
            ;

        primary_expr = strict_double [_val = _1]
            | int_ [_val = _1]
            | lit("true") [_val = true]
            | lit("false") [_val = false]
            | ustring [_val = unicode_(_1) ]
            | attr [_val = construct<attribute>( _1 ) ]
            | '(' >> expr [_val = _1 ] >> ')'
            ;

        attr %= '[' >> +(char_ - ']') >> ']';
#if BOOST_VERSION > 104200
        ustring %= '\'' >> no_skip[*~char_('\'')] >> '\'';
#else
        ustring %= '\'' >> lexeme[*(char_-'\'')] >> '\'';
#endif
    }

    qi::real_parser<double, qi::strict_real_policies<double> > strict_double;
    boost::phoenix::function<unicode_impl> unicode_;
    boost::phoenix::function<regex_match_impl> regex_match_;
    boost::phoenix::function<regex_replace_impl> regex_replace_;
    //
    rule_type expr;
    rule_type equality_expr;
    rule_type cond_expr;
    rule_type relational_expr;
    rule_type logical_expr;
    rule_type additive_expr;
    rule_type multiplicative_expr;
    rule_type not_expr;
    rule_type primary_expr;
    qi::rule<Iterator, std::string() > regex_match_expr;
    qi::rule<Iterator, expr_node(expr_node), qi::locals<std::string,std::string>, space_type> regex_replace_expr;
    qi::rule<Iterator, std::string() , space_type> attr;
    qi::rule<Iterator, std::string() > ustring;
};

} // namespace

#endif  // MAPNIK_EXPRESSIONS_GRAMMAR_HPP
<|endoftext|>


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

#include "dgassert.hpp"

#include <new>
#include <stdint.h>
#include <utility>

namespace DetectorGraph
{

/**
 * @brief Internal - Static allocator for child types of arbitrary sizes.
 *
 * Memory-constrained devices often don't provide a general purpose heap (new
 * & delete). In those cases it's desirable to have an application limit its
 * memory allocations purely to statically allocated memory.
 * DetectorGraph uses the `class Child<T> : class Base` pattern a lot to
 * provide it's richly typed APIs. And in some places it relies on runtime
 * allocation of such `Child<T>` objects. This class provides an allocator
 * for such objects that complies with the no-heap requirement.
 *
 * The one limitation is that it's only able to store 1 object per `T` of
 * `Child<T>`.
 *
 * Usage sample:
 * @code

struct SomeBase { virtual ~SomeBase() {} };
template<class T> struct SomeChild : public SomeBase { };

StaticTypedAllocator<SomeBase, 0> allocator;

SomeBase* objT1 = allocator.New<SomeChild<T1>>();
SomeBase* objT2 = allocator.New<SomeChild<T2>>();
allocator.Delete(objT1);
allocator.Delete(objT2);

 * @endcode
 *
 * Different values for the Ctxt template parameter must be used on separate
 * instances if they store the same types:
 * @code
// Given

StaticTypedAllocator<SomeBase, 0> allocatorA;
SomeBase* objA = allocator.New<SomeChild<T1>>();
// SomeBase* objB = allocator.New<SomeChild<T1>>(); // Will throw a 'busy' assert.

StaticTypedAllocator<SomeBase, 1> allocatorB;
SomeBase* objB = allocatorB.New<SomeChild<T1>>(); // ok

 * @endcode
 *
 *
 */
namespace {
	struct DefaultStaticTypedAllocatorCtxt {};
}

template< class TBase, class Ctxt = DefaultStaticTypedAllocatorCtxt>
class StaticTypedAllocator
{
    struct NodeHeader
    {
        NodeHeader(uint8_t* aStorage)
        : storage(aStorage)
        , next(NULL), busy(false)
        {
        }

        uint8_t* storage;
        TBase* GetObjectPtr()
        {
            return reinterpret_cast<TBase*>(storage);
        }
        NodeHeader* next;
        bool busy;
    };
public:
    StaticTypedAllocator() : mHeadNode(NULL)
    {
    }

    /* Below there are two versions of the New() method.
     * The top one uses C++11 variadic template args and rvalue perfect
     * forwarding. This is both more convenient and more efficient as it
     * constructs the type only once vs constructing & copy constructing. */

    /**
     * @brief Constructs & Allocates new object of type TChild with arguments.
     */
    template <class TChild, typename... TChildArgs>
    TBase* New(TChildArgs&&... constructor_args)
    {
        NodeHeader* node = GetNodeHeader<TChild>();

        DG_ASSERT(!node->busy);
        // NOTE: Cannot store more than one object at the same time.

        TBase* newObjPtr =
            new(node->storage) TChild(std::forward<TChildArgs>(constructor_args)...);

        node->busy = true;
        LinkNode(node);
        return newObjPtr;
    }

    /**
     * @brief Copy-Constructs & Allocates new object of type TChild.
     */
    template<class TChild>
    TBase* New(const TChild& aOriginal)
    {
        NodeHeader* node = GetNodeHeader<TChild>();

        DG_ASSERT(!node->busy);
        // NOTE: Cannot store more than one object at the same time.

        TBase* newObjPtr =
            new(node->storage) TChild(aOriginal);

        node->busy = true;
        LinkNode(node);
        return newObjPtr;
    }

    void Delete(TBase* targetObject)
    {
        // O(N) deletion
        DG_ASSERT(mHeadNode); // Not empty

        // A reference to the .next ptr on the previous node
        NodeHeader** fromPtr = &mHeadNode;

        // Traversing node
        NodeHeader* nodeIt = mHeadNode;

        // Target
        TBase* storedObject = nodeIt->GetObjectPtr();

        while(nodeIt && storedObject != targetObject)
        {
            // Save .next ptr address before following it
            fromPtr = &(nodeIt->next);
            nodeIt = nodeIt->next;
            storedObject = nodeIt->GetObjectPtr();
        }

        DG_ASSERT(nodeIt && storedObject);

        // Bypass deleted node
        *fromPtr = nodeIt->next;

        // Destroy deleted node
        storedObject->~TBase();

        // Cleanup deleted node
        nodeIt->busy = false;
        nodeIt->next = NULL;
    }

    void clear()
    {
        // O(N) clear.
        NodeHeader* nodeIt = mHeadNode;
        while(nodeIt)
        {
            TBase* storedObject = nodeIt->GetObjectPtr();
            storedObject->~TBase();
            nodeIt->busy = false;

            NodeHeader* tmp = nodeIt; // only necessary to cleanup
            nodeIt = nodeIt->next;
            tmp->next = NULL;
        }
        mHeadNode = NULL;
    }

    ~StaticTypedAllocator()
    {
        clear();
    }

private:
    void LinkNode(NodeHeader* node)
    {
        // O(N) insertion.

        // Find insertion point
        NodeHeader** nextPtr = &mHeadNode;
        while(*nextPtr)
        {
            nextPtr = &((*nextPtr)->next);
        }

        // Change last ptr to point to new node instead of NULL
        *nextPtr = node;
        node->next = NULL;
    }

private:
    NodeHeader* mHeadNode;

    template<class TChild>
    NodeHeader* GetNodeHeader()
    {
        static uint8_t mNodeStorage[sizeof(TChild)];
        static NodeHeader node = NodeHeader(mNodeStorage);
        return &node;
    }
};

}
<commit_msg>Added documentation for StaticTypedAllocator public methods<commit_after>// Copyright 2018 Nest Labs, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "dgassert.hpp"

#include <new>
#include <stdint.h>
#include <utility>

namespace DetectorGraph
{

/**
 * @brief Internal - Static allocator for child types of arbitrary sizes.
 *
 * Memory-constrained devices often don't provide a general purpose heap (new
 * & delete). In those cases it's desirable to have an application limit its
 * memory allocations purely to statically allocated memory.
 * DetectorGraph uses the `class Child<T> : class Base` pattern a lot to
 * provide it's richly typed APIs. And in some places it relies on runtime
 * allocation of such `Child<T>` objects. This class provides an allocator
 * for such objects that complies with the no-heap requirement.
 *
 * The one limitation is that it's only able to store 1 object per `T` of
 * `Child<T>`.
 *
 * Usage sample:
 * @code

struct SomeBase { virtual ~SomeBase() {} };
template<class T> struct SomeChild : public SomeBase { };

StaticTypedAllocator<SomeBase, 0> allocator;

SomeBase* objT1 = allocator.New<SomeChild<T1>>();
SomeBase* objT2 = allocator.New<SomeChild<T2>>();
allocator.Delete(objT1);
allocator.Delete(objT2);

 * @endcode
 *
 * Different values for the Ctxt template parameter must be used on separate
 * instances if they store the same types:
 * @code
// Given

StaticTypedAllocator<SomeBase, 0> allocatorA;
SomeBase* objA = allocator.New<SomeChild<T1>>();
// SomeBase* objB = allocator.New<SomeChild<T1>>(); // Will throw a 'busy' assert.

StaticTypedAllocator<SomeBase, 1> allocatorB;
SomeBase* objB = allocatorB.New<SomeChild<T1>>(); // ok

 * @endcode
 *
 *
 */
namespace {
	struct DefaultStaticTypedAllocatorCtxt {};
}

template< class TBase, class Ctxt = DefaultStaticTypedAllocatorCtxt>
class StaticTypedAllocator
{
    struct NodeHeader
    {
        NodeHeader(uint8_t* aStorage)
        : storage(aStorage)
        , next(NULL), busy(false)
        {
        }

        uint8_t* storage;
        TBase* GetObjectPtr()
        {
            return reinterpret_cast<TBase*>(storage);
        }
        NodeHeader* next;
        bool busy;
    };
public:
    StaticTypedAllocator() : mHeadNode(NULL)
    {
    }

    /* Below there are two versions of the New() method.
     * The top one uses C++11 variadic template args and rvalue perfect
     * forwarding. This is both more convenient and more efficient as it
     * constructs the type only once vs constructing & copy constructing. */

    /**
     * @brief Constructs & Allocates new object of type TChild with arguments.
     */
    template <class TChild, typename... TChildArgs>
    TBase* New(TChildArgs&&... constructor_args)
    {
        NodeHeader* node = GetNodeHeader<TChild>();

        DG_ASSERT(!node->busy);
        // NOTE: Cannot store more than one object at the same time.

        TBase* newObjPtr =
            new(node->storage) TChild(std::forward<TChildArgs>(constructor_args)...);

        node->busy = true;
        LinkNode(node);
        return newObjPtr;
    }

    /**
     * @brief Copy-Constructs & Allocates new object of type TChild.
     */
    template<class TChild>
    TBase* New(const TChild& aOriginal)
    {
        NodeHeader* node = GetNodeHeader<TChild>();

        DG_ASSERT(!node->busy);
        // NOTE: Cannot store more than one object at the same time.

        TBase* newObjPtr =
            new(node->storage) TChild(aOriginal);

        node->busy = true;
        LinkNode(node);
        return newObjPtr;
    }

    /**
     * @brief Deletes/Frees an allocated object via the base ptr.
     */
    void Delete(TBase* targetObject)
    {
        // O(N) deletion
        DG_ASSERT(mHeadNode); // Not empty

        // A reference to the .next ptr on the previous node
        NodeHeader** fromPtr = &mHeadNode;

        // Traversing node
        NodeHeader* nodeIt = mHeadNode;

        // Target
        TBase* storedObject = nodeIt->GetObjectPtr();

        while(nodeIt && storedObject != targetObject)
        {
            // Save .next ptr address before following it
            fromPtr = &(nodeIt->next);
            nodeIt = nodeIt->next;
            storedObject = nodeIt->GetObjectPtr();
        }

        DG_ASSERT(nodeIt && storedObject);

        // Bypass deleted node
        *fromPtr = nodeIt->next;

        // Destroy deleted node
        storedObject->~TBase();

        // Cleanup deleted node
        nodeIt->busy = false;
        nodeIt->next = NULL;
    }

    /**
     * @brief Deletes all allocated objects.
     */
    void clear()
    {
        // O(N) clear.
        NodeHeader* nodeIt = mHeadNode;
        while(nodeIt)
        {
            TBase* storedObject = nodeIt->GetObjectPtr();
            storedObject->~TBase();
            nodeIt->busy = false;

            NodeHeader* tmp = nodeIt; // only necessary to cleanup
            nodeIt = nodeIt->next;
            tmp->next = NULL;
        }
        mHeadNode = NULL;
    }

    ~StaticTypedAllocator()
    {
        clear();
    }

private:
    void LinkNode(NodeHeader* node)
    {
        // O(N) insertion.

        // Find insertion point
        NodeHeader** nextPtr = &mHeadNode;
        while(*nextPtr)
        {
            nextPtr = &((*nextPtr)->next);
        }

        // Change last ptr to point to new node instead of NULL
        *nextPtr = node;
        node->next = NULL;
    }

private:
    NodeHeader* mHeadNode;

    template<class TChild>
    NodeHeader* GetNodeHeader()
    {
        static uint8_t mNodeStorage[sizeof(TChild)];
        static NodeHeader node = NodeHeader(mNodeStorage);
        return &node;
    }
};

}
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*! @file
    @brief  input クラス @n
			数値、文字列などの入力クラス
			Copyright 2017 Kunihito Hiramatsu
    @author 平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <cstdint>

extern "C" {

	char sci_getch(void);

};

namespace utils {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  標準入力ファンクタ
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	class def_chainp {
		const char* str_;
		char		last_;
		bool		unget_;
	public:
		def_chainp(const char* str = nullptr) : str_(str), last_(0), unget_(false) { }

		void unget() {
			unget_ = true;
		}

		char operator() () {
			if(unget_) {
				unget_ = false;
			} else {
				if(str_ == nullptr) {
					last_ = sci_getch();
				} else {
					last_ = *str_;
					if(last_ != 0) { ++str_; }
				}
			}
			return last_;
		}
	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  汎用入力クラス
		@param[in]	INP	入力クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class INP>
	class basic_input {

		const char*	form_;

		INP			inp_;

		uint32_t bin_() {
			uint32_t a = 0;
			char ch;
			while((ch = inp_()) != 0 && ch >= '0' && ch <= '1') {
				a <<= 1;
				a += ch - '0';
			}
			return a;
		}

		uint32_t oct_() {
			uint32_t a = 0;
			char ch;
			while((ch = inp_()) != 0 && ch >= '0' && ch <= '7') {
				a <<= 3;
				a += ch - '0';
			}
			return a;
		}

		uint32_t dec_() {
			uint32_t a = 0;
			char ch;
			while((ch = inp_()) != 0 && ch >= '0' && ch <= '9') {
				a *= 10;
				a += ch - '0';
			}
			return a;
		}

		uint32_t hex_() {
			uint32_t a = 0;
			char ch;
			while((ch = inp_()) != 0) {
				if(ch >= '0' && ch <= '9') {
					a <<= 4;
					a += ch - '0';
				} else if(ch >= 'A' && ch <= 'F') {
					a <<= 4;
					a += ch - 'A' + 10;
				} else if(ch >= 'a' && ch <= 'f') {
					a <<= 4;
					a += ch - 'a' + 10;
				} else {
					break;
				}
			}
			return a;
		}

		enum class mode : uint8_t {
			NONE,
			BIN,
			OCT,
			DEC,
			HEX,
		};
		mode	mode_;
		bool	err_;

		static uint16_t	cnvcnt_;

		enum class fmm : uint8_t {
			none,
			type,

		};

		void next_()
		{
			fmm cm = fmm::none;
			char ch;
			while((ch = *form_++) != 0) {
				switch(cm) {
				case fmm::none:
					if(ch == '[') {
						auto a = inp_();
						const char* p = form_;
						bool ok = false;
						while((ch = *p++) != 0 && ch != ']') {
							if(ch == a) ok = true;
						}
						form_ = p;
						if(!ok) {
							err_ = true;
							return;
						}
					} else if(ch == '%' && *form_ != '%') {
						cm = fmm::type;
					} else if(ch != inp_()) {
						err_ = true;
						return;
					}
					break;
				case fmm::type:
					if(ch == 'b' || ch == 'B') {
						mode_ = mode::BIN;
					} else if(ch == 'o' || ch == 'O') {
						mode_ = mode::OCT;
					} else if(ch == 'd' || ch == 'D') {
						mode_ = mode::DEC;
					} else if(ch == 'x' || ch == 'X') {
						mode_ = mode::HEX;
					} else {
						err_ = true;
					}
					return;
				}
			}
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
			@param[in]	form	入力形式
			@param[in]	inp		変換文字列（nullptrの場合、sci_getch で取得）
		*/
		//-----------------------------------------------------------------//
		basic_input(const char* form, const char* inp = nullptr) : form_(form), inp_(inp),
			mode_(mode::NONE), err_(false)
		{
			cnvcnt_ = 0;
			next_();
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  正常変換数を取得
			@return 正常変換数
		*/
		//-----------------------------------------------------------------//
		static uint16_t get_conversion() { return cnvcnt_; }

		//-----------------------------------------------------------------//
		/*!
			@brief  オペレーター「%」（int32_t）
			@param[in]	val	整数値
			@return	自分の参照
		*/
		//-----------------------------------------------------------------//
		basic_input& operator % (int32_t& val)
		{
			if(err_) return *this;

			bool neg = false;
			{
				auto s = inp_();
				if(s == '-') { neg = true; }
				else if(s == '+') { neg = false; }
				else inp_.unget();
			}
			uint32_t v;
			switch(mode_) {
			case mode::BIN:
				v = bin_();
				break;
			case mode::OCT:
				v = oct_();
				break;
			case mode::DEC:
				v = dec_();
				break;
			case mode::HEX:
				v = hex_();
				break;
			default:
				err_ = true;
				break;
			}
			if(neg) val = -static_cast<int>(v);
			else val = static_cast<int>(v);
			if(!err_) {
				++cnvcnt_;
				inp_.unget();
				next_();
			}
			return *this;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  オペレーター「%」（uint32_t）
			@param[in]	val	整数値
			@return	自分の参照
		*/
		//-----------------------------------------------------------------//
		basic_input& operator % (uint32_t& val)
		{
			if(err_) return *this;

			uint32_t v;
			switch(mode_) {
			case mode::BIN:
				v = bin_();
				break;
			case mode::OCT:
				v = oct_();
				break;
			case mode::DEC:
				v = dec_();
				break;
			case mode::HEX:
				v = hex_();
				break;
			default:
				err_ = true;
				break;
			}
			if(!err_) {
				++cnvcnt_;
				inp_.unget();
				next_();
				val = v;
			}
			return *this;
		}
	};

	template<class INP> uint16_t basic_input<INP>::cnvcnt_;

	typedef basic_input<def_chainp> input;

}
<commit_msg>update float<commit_after>#pragma once
//=====================================================================//
/*! @file
    @brief  input クラス @n
			数値、文字列などの入力クラス
			Copyright 2017 Kunihito Hiramatsu
    @author 平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <type_traits>

extern "C" {

	char sci_getch(void);

};

namespace utils {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  標準入力ファンクタ
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	class def_chainp {
		const char* str_;
		char		last_;
		bool		unget_;
	public:
		def_chainp(const char* str = nullptr) : str_(str), last_(0), unget_(false) { }

		void unget() {
			unget_ = true;
		}

		char operator() () {
			if(unget_) {
				unget_ = false;
			} else {
				if(str_ == nullptr) {
					last_ = sci_getch();
				} else {
					last_ = *str_;
					if(last_ != 0) { ++str_; }
				}
			}
			return last_;
		}
	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  汎用入力クラス
		@param[in]	INP	入力クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class INP>
	class basic_input {

		const char*	form_;

		INP			inp_;

		uint32_t bin_() {
			uint32_t a = 0;
			char ch;
			while((ch = inp_()) != 0 && ch >= '0' && ch <= '1') {
				a <<= 1;
				a += ch - '0';
			}
			return a;
		}

		uint32_t oct_() {
			uint32_t a = 0;
			char ch;
			while((ch = inp_()) != 0 && ch >= '0' && ch <= '7') {
				a <<= 3;
				a += ch - '0';
			}
			return a;
		}

		uint32_t dec_() {
			uint32_t a = 0;
			char ch;
			while((ch = inp_()) != 0 && ch >= '0' && ch <= '9') {
				a *= 10;
				a += ch - '0';
			}
			return a;
		}

		uint32_t hex_() {
			uint32_t a = 0;
			char ch;
			while((ch = inp_()) != 0) {
				if(ch >= '0' && ch <= '9') {
					a <<= 4;
					a += ch - '0';
				} else if(ch >= 'A' && ch <= 'F') {
					a <<= 4;
					a += ch - 'A' + 10;
				} else if(ch >= 'a' && ch <= 'f') {
					a <<= 4;
					a += ch - 'a' + 10;
				} else {
					break;
				}
			}
			return a;
		}

		float real_() {
			uint32_t a = 0;
			uint32_t b = 0;
			uint32_t c = 1;
			char ch;
			bool p = false;
			while((ch = inp_()) != 0) {
				if(ch >= '0' && ch <= '9') {
					a *= 10;
					a += ch - '0';
					c *= 10;
				} else if(ch == '.') {
					b = a;
					a = 0;
					c = 1;
					p = true;
				} else {
					break;
				}
			}
			if(p) {
				return static_cast<float>(b) + static_cast<float>(a) / static_cast<float>(c);
			} else {
				return static_cast<float>(a);
			}
		}

		enum class mode : uint8_t {
			NONE,
			BIN,
			OCT,
			DEC,
			HEX,
			FLOAT,
		};
		mode	mode_;
		bool	err_;

		int		num_;

		enum class fmm : uint8_t {
			none,
			type,

		};

		void next_()
		{
			fmm cm = fmm::none;
			char ch;
			while((ch = *form_++) != 0) {
				switch(cm) {
				case fmm::none:
					if(ch == '[') {
						auto a = inp_();
						const char* p = form_;
						bool ok = false;
						while((ch = *p++) != 0 && ch != ']') {
							if(ch == a) ok = true;
						}
						form_ = p;
						if(!ok) {
							err_ = true;
							return;
						}
					} else if(ch == '%' && *form_ != '%') {
						cm = fmm::type;
					} else if(ch != inp_()) {
						err_ = true;
						return;
					}
					break;

				case fmm::type:
					if(ch >= 0x60) ch -= 0x20;
					if(ch == 'B') {
						mode_ = mode::BIN;
					} else if(ch == 'O') {
						mode_ = mode::OCT;
					} else if(ch == 'D') {
						mode_ = mode::DEC;
					} else if(ch == 'X') {
						mode_ = mode::HEX;
					} else if(ch == 'F') {
						mode_ = mode::FLOAT;
					} else {
						err_ = true;
					}
					return;
				}
			}
			if(ch == 0 && inp_() == 0) ;
			else {
				err_ = true;
			}
		}

		bool neg_() {
			bool neg = false;
			auto s = inp_();
			if(s == '-') { neg = true; }
			else if(s == '+') { neg = false; }
			else inp_.unget();
			return neg;
		}

		int32_t nb_int_(bool sign = true)
		{
			auto neg = neg_();

			uint32_t v = 0;
			switch(mode_) {
			case mode::BIN:
				v = bin_();
				break;
			case mode::OCT:
				v = oct_();
				break;
			case mode::DEC:
				v = dec_();
				break;
			case mode::HEX:
				v = hex_();
				break;
			default:
				err_ = true;
				break;
			}
			if(!err_) {
				inp_.unget();
				next_();
				if(!err_) ++num_;
			}
			if(sign && neg) return -static_cast<int32_t>(v);
			else return static_cast<int32_t>(v);
		}

		float nb_real_()
		{
			bool neg = neg_();

			float v = 0.0f;
			switch(mode_) {
			case mode::FLOAT:
				v = real_();
				break;
			default:
				err_ = true;
				break;
			}
			if(!err_) {
				inp_.unget();
				next_();
				if(!err_) ++num_;
			}
			if(neg) return -v;
			else return v;
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
			@param[in]	form	入力形式
			@param[in]	inp		変換文字列（nullptrの場合、sci_getch で取得）
		*/
		//-----------------------------------------------------------------//
		basic_input(const char* form, const char* inp = nullptr) : form_(form), inp_(inp),
			mode_(mode::NONE), err_(false), num_(0)
		{
			next_();
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  正常変換数を取得
			@return 正常変換数
		*/
		//-----------------------------------------------------------------//
		int num() const { return num_; }

		//-----------------------------------------------------------------//
		/*!
			@brief  テンプレート・オペレーター「%」
			@param[in]	val	整数型
			@return	自分の参照
		*/
		//-----------------------------------------------------------------//
		template <typename T>
		basic_input& operator % (T& val)
		{
			if(err_) return *this;

			if(std::is_floating_point<T>::value) {
				val = nb_real_();
			} else {
				val = nb_int_(std::is_signed<T>::value);
			}
			return *this;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  オペレーター「=」
		*/
		//-----------------------------------------------------------------//
		basic_input& operator = (const basic_input& in) { return *this; }
	};

	typedef basic_input<def_chainp> input;
}
<|endoftext|>


<commit_before>//===- DependenceAnalysis.cpp - Dependence analysis on SSA views ----------===//
//
// Copyright 2019 The MLIR Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// =============================================================================
//
// This file implements view-based alias and dependence analyses.
//
//===----------------------------------------------------------------------===//

#include "mlir/Dialect/Linalg/Analysis/DependenceAnalysis.h"
#include "mlir/Dialect/Linalg/IR/LinalgOps.h"
#include "mlir/Dialect/StandardOps/Ops.h"

#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"

#define DEBUG_TYPE "linalg-dependence-analysis"

using namespace mlir;
using namespace mlir::linalg;

using llvm::dbgs;

static StringRef toStringRef(LinalgDependenceGraph::DependenceType dt) {
  switch (dt) {
  case LinalgDependenceGraph::DependenceType::RAW:
    return "RAW";
  case LinalgDependenceGraph::DependenceType::RAR:
    return "RAR";
  case LinalgDependenceGraph::DependenceType::WAR:
    return "WAR";
  case LinalgDependenceGraph::DependenceType::WAW:
    return "WAW";
  default:
    break;
  }
  llvm_unreachable("Unexpected DependenceType");
}

Value *Aliases::find(Value *v) {
  if (isa<BlockArgument>(v))
    return v;

  auto it = aliases.find(v);
  if (it != aliases.end()) {
    assert(((isa<BlockArgument>(it->getSecond()) &&
             it->getSecond()->getType().isa<MemRefType>()) ||
            it->getSecond()->getType().isa<BufferType>()) &&
           "Buffer or block argument expected");
    return it->getSecond();
  }

  while (true) {
    if (isa<BlockArgument>(v))
      return v;
    if (auto alloc = dyn_cast_or_null<AllocOp>(v->getDefiningOp())) {
      if (isStrided(alloc.getType()))
        return alloc.getResult();
    }
    if (auto slice = dyn_cast_or_null<SliceOp>(v->getDefiningOp())) {
      auto it = aliases.insert(std::make_pair(v, find(slice.view())));
      return it.first->second;
    }
    if (auto view = dyn_cast_or_null<ViewOp>(v->getDefiningOp())) {
      auto it = aliases.insert(std::make_pair(v, view.source()));
      return it.first->second;
    }
    if (auto view = dyn_cast_or_null<SubViewOp>(v->getDefiningOp())) {
      v = view.source();
      continue;
    }
    llvm::errs() << "View alias analysis reduces to: " << *v << "\n";
    llvm_unreachable("unsupported view alias case");
  }
}

LinalgDependenceGraph
LinalgDependenceGraph::buildDependenceGraph(Aliases &aliases, FuncOp f) {
  SmallVector<Operation *, 8> linalgOps;
  f.walk([&](LinalgOp op) { linalgOps.push_back(op); });
  return LinalgDependenceGraph(aliases, linalgOps);
}

LinalgDependenceGraph::LinalgDependenceGraph(Aliases &aliases,
                                             ArrayRef<Operation *> ops)
    : aliases(aliases), linalgOps(ops.begin(), ops.end()) {
  for (auto en : llvm::enumerate(linalgOps)) {
    assert(isa<LinalgOp>(en.value()) && "Expected value for LinalgOp");
    linalgOpPositions.insert(std::make_pair(en.value(), en.index()));
  }
  for (unsigned i = 0, e = ops.size(); i < e; ++i) {
    for (unsigned j = i + 1; j < e; ++j) {
      addDependencesBetween(cast<LinalgOp>(ops[i]), cast<LinalgOp>(ops[j]));
    }
  }
}

void LinalgDependenceGraph::addDependenceElem(DependenceType dt,
                                              LinalgOpView indexingOpView,
                                              LinalgOpView dependentOpView) {
  LLVM_DEBUG(dbgs() << "\nAdd dep type " << toStringRef(dt) << ":\t"
                    << *indexingOpView.op << " -> " << *dependentOpView.op);
  dependencesFromGraphs[dt][indexingOpView.op].push_back(
      LinalgDependenceGraphElem{dependentOpView, indexingOpView.view});
  dependencesIntoGraphs[dt][dependentOpView.op].push_back(
      LinalgDependenceGraphElem{indexingOpView, dependentOpView.view});
}

LinalgDependenceGraph::dependence_range
LinalgDependenceGraph::getDependencesFrom(
    LinalgOp src, LinalgDependenceGraph::DependenceType dt) const {
  return getDependencesFrom(src.getOperation(), dt);
}

LinalgDependenceGraph::dependence_range
LinalgDependenceGraph::getDependencesFrom(
    Operation *src, LinalgDependenceGraph::DependenceType dt) const {
  auto iter = dependencesFromGraphs[dt].find(src);
  if (iter == dependencesFromGraphs[dt].end())
    return llvm::make_range(nullptr, nullptr);
  return llvm::make_range(iter->second.begin(), iter->second.end());
}

LinalgDependenceGraph::dependence_range
LinalgDependenceGraph::getDependencesInto(
    LinalgOp dst, LinalgDependenceGraph::DependenceType dt) const {
  return getDependencesInto(dst.getOperation(), dt);
}

LinalgDependenceGraph::dependence_range
LinalgDependenceGraph::getDependencesInto(
    Operation *dst, LinalgDependenceGraph::DependenceType dt) const {
  auto iter = dependencesIntoGraphs[dt].find(dst);
  if (iter == dependencesIntoGraphs[dt].end())
    return llvm::make_range(nullptr, nullptr);
  return llvm::make_range(iter->second.begin(), iter->second.end());
}

void LinalgDependenceGraph::addDependencesBetween(LinalgOp src, LinalgOp dst) {
  for (auto *srcView : src.getOutputs()) { // W
    // RAW graph
    for (auto *dstView : dst.getInputs()) {  // R
      if (aliases.alias(srcView, dstView)) { // if alias, fill RAW
        addDependenceElem(DependenceType::RAW,
                          LinalgOpView{src.getOperation(), srcView},
                          LinalgOpView{dst.getOperation(), dstView});
      }
    }
    // WAW graph
    for (auto *dstView : dst.getOutputs()) { // W
      if (aliases.alias(srcView, dstView)) { // if alias, fill WAW
        addDependenceElem(DependenceType::WAW,
                          LinalgOpView{src.getOperation(), srcView},
                          LinalgOpView{dst.getOperation(), dstView});
      }
    }
  }
  for (auto *srcView : src.getInputs()) { // R
    // RAR graph
    for (auto *dstView : dst.getInputs()) {  // R
      if (aliases.alias(srcView, dstView)) { // if alias, fill RAR
        addDependenceElem(DependenceType::RAR,
                          LinalgOpView{src.getOperation(), srcView},
                          LinalgOpView{dst.getOperation(), dstView});
      }
    }
    // WAR graph
    for (auto *dstView : dst.getOutputs()) { // W
      if (aliases.alias(srcView, dstView)) { // if alias, fill WAR
        addDependenceElem(DependenceType::WAR,
                          LinalgOpView{src.getOperation(), srcView},
                          LinalgOpView{dst.getOperation(), dstView});
      }
    }
  }
}

SmallVector<Operation *, 8>
LinalgDependenceGraph::findCoveringDependences(LinalgOp srcLinalgOp,
                                               LinalgOp dstLinalgOp) const {
  return findOperationsWithCoveringDependences(
      srcLinalgOp, dstLinalgOp, nullptr,
      {DependenceType::WAW, DependenceType::WAR, DependenceType::RAW});
}

SmallVector<Operation *, 8> LinalgDependenceGraph::findCoveringWrites(
    LinalgOp srcLinalgOp, LinalgOp dstLinalgOp, Value *view) const {
  return findOperationsWithCoveringDependences(
      srcLinalgOp, dstLinalgOp, view,
      {DependenceType::WAW, DependenceType::WAR});
}

SmallVector<Operation *, 8> LinalgDependenceGraph::findCoveringReads(
    LinalgOp srcLinalgOp, LinalgOp dstLinalgOp, Value *view) const {
  return findOperationsWithCoveringDependences(
      srcLinalgOp, dstLinalgOp, view,
      {DependenceType::RAR, DependenceType::RAW});
}

SmallVector<Operation *, 8>
LinalgDependenceGraph::findOperationsWithCoveringDependences(
    LinalgOp srcLinalgOp, LinalgOp dstLinalgOp, Value *view,
    ArrayRef<DependenceType> types) const {
  auto *src = srcLinalgOp.getOperation();
  auto *dst = dstLinalgOp.getOperation();
  auto srcPos = linalgOpPositions.lookup(src);
  auto dstPos = linalgOpPositions.lookup(dst);
  assert(srcPos < dstPos && "expected dst after src in IR traversal order");

  SmallVector<Operation *, 8> res;
  // Consider an intermediate interleaved `interim` op, look for any dependence
  // to an aliasing view on a src -> op -> dst path.
  // TODO(ntv) we are not considering paths yet, just interleaved positions.
  for (auto dt : types) {
    for (auto dependence : getDependencesFrom(src, dt)) {
      auto interimPos = linalgOpPositions.lookup(dependence.dependentOpView.op);
      // Skip if not interleaved.
      if (interimPos >= dstPos || interimPos <= srcPos)
        continue;
      if (view && !aliases.alias(view, dependence.indexingView))
        continue;
      auto *op = dependence.dependentOpView.op;
      LLVM_DEBUG(dbgs() << "\n***Found covering dependence of type "
                        << toStringRef(dt) << ": " << *src << " -> " << *op
                        << " on " << *dependence.indexingView);
      res.push_back(op);
    }
  }
  return res;
}
<commit_msg>Fix build warnings<commit_after>//===- DependenceAnalysis.cpp - Dependence analysis on SSA views ----------===//
//
// Copyright 2019 The MLIR Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// =============================================================================
//
// This file implements view-based alias and dependence analyses.
//
//===----------------------------------------------------------------------===//

#include "mlir/Dialect/Linalg/Analysis/DependenceAnalysis.h"
#include "mlir/Dialect/Linalg/IR/LinalgOps.h"
#include "mlir/Dialect/StandardOps/Ops.h"

#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"

#define DEBUG_TYPE "linalg-dependence-analysis"

using namespace mlir;
using namespace mlir::linalg;

using llvm::dbgs;

static StringRef toStringRef(LinalgDependenceGraph::DependenceType dt) {
  switch (dt) {
  case LinalgDependenceGraph::DependenceType::RAW:
    return "RAW";
  case LinalgDependenceGraph::DependenceType::RAR:
    return "RAR";
  case LinalgDependenceGraph::DependenceType::WAR:
    return "WAR";
  case LinalgDependenceGraph::DependenceType::WAW:
    return "WAW";
  default:
    break;
  }
  llvm_unreachable("Unexpected DependenceType");
}

Value *Aliases::find(Value *v) {
  if (isa<BlockArgument>(v))
    return v;

  auto it = aliases.find(v);
  if (it != aliases.end()) {
    assert(((isa<BlockArgument>(it->getSecond()) &&
             it->getSecond()->getType().isa<MemRefType>()) ||
            it->getSecond()->getType().isa<BufferType>()) &&
           "Buffer or block argument expected");
    return it->getSecond();
  }

  while (true) {
    if (isa<BlockArgument>(v))
      return v;
    if (auto alloc = dyn_cast_or_null<AllocOp>(v->getDefiningOp())) {
      if (isStrided(alloc.getType()))
        return alloc.getResult();
    }
    if (auto slice = dyn_cast_or_null<SliceOp>(v->getDefiningOp())) {
      auto it = aliases.insert(std::make_pair(v, find(slice.view())));
      return it.first->second;
    }
    if (auto view = dyn_cast_or_null<ViewOp>(v->getDefiningOp())) {
      auto it = aliases.insert(std::make_pair(v, view.source()));
      return it.first->second;
    }
    if (auto view = dyn_cast_or_null<SubViewOp>(v->getDefiningOp())) {
      v = view.source();
      continue;
    }
    llvm::errs() << "View alias analysis reduces to: " << *v << "\n";
    llvm_unreachable("unsupported view alias case");
  }
}

LinalgDependenceGraph
LinalgDependenceGraph::buildDependenceGraph(Aliases &aliases, FuncOp f) {
  SmallVector<Operation *, 8> linalgOps;
  f.walk([&](LinalgOp op) { linalgOps.push_back(op); });
  return LinalgDependenceGraph(aliases, linalgOps);
}

LinalgDependenceGraph::LinalgDependenceGraph(Aliases &aliases,
                                             ArrayRef<Operation *> ops)
    : aliases(aliases), linalgOps(ops.begin(), ops.end()) {
  for (auto en : llvm::enumerate(linalgOps)) {
    assert(isa<LinalgOp>(en.value()) && "Expected value for LinalgOp");
    linalgOpPositions.insert(std::make_pair(en.value(), en.index()));
  }
  for (unsigned i = 0, e = ops.size(); i < e; ++i) {
    for (unsigned j = i + 1; j < e; ++j) {
      addDependencesBetween(cast<LinalgOp>(ops[i]), cast<LinalgOp>(ops[j]));
    }
  }
}

void LinalgDependenceGraph::addDependenceElem(DependenceType dt,
                                              LinalgOpView indexingOpView,
                                              LinalgOpView dependentOpView) {
  LLVM_DEBUG(dbgs() << "\nAdd dep type " << toStringRef(dt) << ":\t"
                    << *indexingOpView.op << " -> " << *dependentOpView.op);
  (void)toStringRef;
  dependencesFromGraphs[dt][indexingOpView.op].push_back(
      LinalgDependenceGraphElem{dependentOpView, indexingOpView.view});
  dependencesIntoGraphs[dt][dependentOpView.op].push_back(
      LinalgDependenceGraphElem{indexingOpView, dependentOpView.view});
}

LinalgDependenceGraph::dependence_range
LinalgDependenceGraph::getDependencesFrom(
    LinalgOp src, LinalgDependenceGraph::DependenceType dt) const {
  return getDependencesFrom(src.getOperation(), dt);
}

LinalgDependenceGraph::dependence_range
LinalgDependenceGraph::getDependencesFrom(
    Operation *src, LinalgDependenceGraph::DependenceType dt) const {
  auto iter = dependencesFromGraphs[dt].find(src);
  if (iter == dependencesFromGraphs[dt].end())
    return llvm::make_range(nullptr, nullptr);
  return llvm::make_range(iter->second.begin(), iter->second.end());
}

LinalgDependenceGraph::dependence_range
LinalgDependenceGraph::getDependencesInto(
    LinalgOp dst, LinalgDependenceGraph::DependenceType dt) const {
  return getDependencesInto(dst.getOperation(), dt);
}

LinalgDependenceGraph::dependence_range
LinalgDependenceGraph::getDependencesInto(
    Operation *dst, LinalgDependenceGraph::DependenceType dt) const {
  auto iter = dependencesIntoGraphs[dt].find(dst);
  if (iter == dependencesIntoGraphs[dt].end())
    return llvm::make_range(nullptr, nullptr);
  return llvm::make_range(iter->second.begin(), iter->second.end());
}

void LinalgDependenceGraph::addDependencesBetween(LinalgOp src, LinalgOp dst) {
  for (auto *srcView : src.getOutputs()) { // W
    // RAW graph
    for (auto *dstView : dst.getInputs()) {  // R
      if (aliases.alias(srcView, dstView)) { // if alias, fill RAW
        addDependenceElem(DependenceType::RAW,
                          LinalgOpView{src.getOperation(), srcView},
                          LinalgOpView{dst.getOperation(), dstView});
      }
    }
    // WAW graph
    for (auto *dstView : dst.getOutputs()) { // W
      if (aliases.alias(srcView, dstView)) { // if alias, fill WAW
        addDependenceElem(DependenceType::WAW,
                          LinalgOpView{src.getOperation(), srcView},
                          LinalgOpView{dst.getOperation(), dstView});
      }
    }
  }
  for (auto *srcView : src.getInputs()) { // R
    // RAR graph
    for (auto *dstView : dst.getInputs()) {  // R
      if (aliases.alias(srcView, dstView)) { // if alias, fill RAR
        addDependenceElem(DependenceType::RAR,
                          LinalgOpView{src.getOperation(), srcView},
                          LinalgOpView{dst.getOperation(), dstView});
      }
    }
    // WAR graph
    for (auto *dstView : dst.getOutputs()) { // W
      if (aliases.alias(srcView, dstView)) { // if alias, fill WAR
        addDependenceElem(DependenceType::WAR,
                          LinalgOpView{src.getOperation(), srcView},
                          LinalgOpView{dst.getOperation(), dstView});
      }
    }
  }
}

SmallVector<Operation *, 8>
LinalgDependenceGraph::findCoveringDependences(LinalgOp srcLinalgOp,
                                               LinalgOp dstLinalgOp) const {
  return findOperationsWithCoveringDependences(
      srcLinalgOp, dstLinalgOp, nullptr,
      {DependenceType::WAW, DependenceType::WAR, DependenceType::RAW});
}

SmallVector<Operation *, 8> LinalgDependenceGraph::findCoveringWrites(
    LinalgOp srcLinalgOp, LinalgOp dstLinalgOp, Value *view) const {
  return findOperationsWithCoveringDependences(
      srcLinalgOp, dstLinalgOp, view,
      {DependenceType::WAW, DependenceType::WAR});
}

SmallVector<Operation *, 8> LinalgDependenceGraph::findCoveringReads(
    LinalgOp srcLinalgOp, LinalgOp dstLinalgOp, Value *view) const {
  return findOperationsWithCoveringDependences(
      srcLinalgOp, dstLinalgOp, view,
      {DependenceType::RAR, DependenceType::RAW});
}

SmallVector<Operation *, 8>
LinalgDependenceGraph::findOperationsWithCoveringDependences(
    LinalgOp srcLinalgOp, LinalgOp dstLinalgOp, Value *view,
    ArrayRef<DependenceType> types) const {
  auto *src = srcLinalgOp.getOperation();
  auto *dst = dstLinalgOp.getOperation();
  auto srcPos = linalgOpPositions.lookup(src);
  auto dstPos = linalgOpPositions.lookup(dst);
  assert(srcPos < dstPos && "expected dst after src in IR traversal order");

  SmallVector<Operation *, 8> res;
  // Consider an intermediate interleaved `interim` op, look for any dependence
  // to an aliasing view on a src -> op -> dst path.
  // TODO(ntv) we are not considering paths yet, just interleaved positions.
  for (auto dt : types) {
    for (auto dependence : getDependencesFrom(src, dt)) {
      auto interimPos = linalgOpPositions.lookup(dependence.dependentOpView.op);
      // Skip if not interleaved.
      if (interimPos >= dstPos || interimPos <= srcPos)
        continue;
      if (view && !aliases.alias(view, dependence.indexingView))
        continue;
      auto *op = dependence.dependentOpView.op;
      LLVM_DEBUG(dbgs() << "\n***Found covering dependence of type "
                        << toStringRef(dt) << ": " << *src << " -> " << *op
                        << " on " << *dependence.indexingView);
      res.push_back(op);
    }
  }
  return res;
}
<|endoftext|>


<commit_before>#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include "catch_reporter_automake.hpp"
#include "catch_reporter_tap.hpp"<commit_msg>Update catch_main.cxx<commit_after>#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include "catch_reporter_tap.hpp"
<|endoftext|>


<commit_before>#include"variables.hpp"
#include"processes.hpp"
#include"bytecodes.hpp"
#include<iostream>

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

	/*tests!*/
	Process proc;
	/*allocate stuff*/
	//(cons 'bar ...)
	proc.stack.push(new(proc) Sym(globals->lookup("bar")));
	//(cons 'foo ...)
	proc.stack.push(new(proc) Sym(globals->lookup("foo")));
	//(cons t ...)
	proc.stack.push(new(proc) Sym(TATOM));//t
	//(cons t nil)
	proc.stack.push(new(proc) Sym(TATOM)); //t
	proc.stack.push(new(proc) Sym(NILATOM)); //nil
	//cons
	bytecode_cons(proc);
	//repush stack top to make shared structure
	proc.stack.push(proc.stack.top());
	bytecode_cons(proc);
	bytecode_cons(proc);
	bytecode_cons(proc);

	proc.stack.top()->probe(0);
}

<commit_msg>Added test for integer allocation<commit_after>#include"variables.hpp"
#include"processes.hpp"
#include"bytecodes.hpp"
#include<iostream>

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

	/*tests!*/
	Process proc;
	/*allocate stuff*/
	//(cons 'bar ...)
	proc.stack.push(new(proc) Sym(globals->lookup("bar")));
	//(cons 'foo ...)
	proc.stack.push(new(proc) Sym(globals->lookup("foo")));
	//(cons t ...)
	proc.stack.push(new(proc) Sym(TATOM));//t
	//(cons t nil)
	proc.stack.push(new(proc) Sym(TATOM)); //t
	proc.stack.push(new(proc) Sym(NILATOM)); //nil
	//cons
	bytecode_cons(proc);
	//repush stack top to make shared structure
	proc.stack.push(proc.stack.top());
	bytecode_cons(proc);
	bytecode_cons(proc);
	bytecode_cons(proc);
	//int
	proc.stack.push(new(proc) Integer(1));
	proc.stack.push(new(proc) Integer(-1));
	bytecode_cons(proc);
	bytecode_cons(proc);

	proc.stack.top()->probe(0);
}

<|endoftext|>


<commit_before>#include "stdafx.h"
#include "EnVistasGeometryPlugin.h"
#include <stdexcept>
#include <EnvExtension.h>
#include <Maplayer.h>
#include <vector>
#include <boost/thread/locks.hpp>
#include "SHP3DUtility.h"
#include <EnvEngine/DeltaArray.h>
#include <EnvInterface.h>
#include "EnvContextObservable.h"

using std::vector;
using std::logic_error;
using std::runtime_error;
using std::map;
using std::shared_ptr;

// this is the most ridiculous build error...
wxEvtHandler::wxEvtHandler(const wxEvtHandler&) { }

static const VI_String METHOD_FOR_VISTAS_ERROR("This class is for interfacing with \
												ENVISION. Most method are not \
												implemented; they are for VISTAS.");

static const VI_String NOT_YET_IMPLEMENTED_ERROR("Not implemented yet. Talk to Vir\
												 about this.");

EnVistasGeometryPlugin::EnVistasGeometryPlugin(
	std::shared_ptr<EnvContextObservable>& observable)
{
	_observable = observable;
	_envContext = _observable->GetEnvContext();
	auto polyArray = _envContext->pMapLayer->m_pPolyArray;
	unsigned numShapes = polyArray->GetCount();
	shared_ptr<vector<VI_Shape>> shapeArray(new vector<VI_Shape>(numShapes));
	for (unsigned i = 0; i < numShapes; i++) {
		auto shape = polyArray->ElementAt(i);
		CDWordArray& parts = shape->m_vertexPartArray;
		auto numParts = parts.GetCount();
		VertexArray& vertices = shape->m_vertexArray;
		auto numVerts = vertices.GetCount();

		shapeArray->at(i).ShapeHeader.numparts = numParts;
		shapeArray->at(i).ShapeHeader.numpoints = numVerts;
		shapeArray->at(i).ShapeHeader.xmax = shape->m_xMax;
		shapeArray->at(i).ShapeHeader.xmin = shape->m_xMin;
		shapeArray->at(i).ShapeHeader.ymin = shape->m_yMin;
		shapeArray->at(i).ShapeHeader.ymax = shape->m_yMax;
		float zmin, zmax;
		shape->GetBoundingZ(zmin, zmax);
		shapeArray->at(i).ShapeHeader.zmin = zmin;
		shapeArray->at(i).ShapeHeader.zmax = zmax;
		shapeArray->at(i).ShapeType = 15;
		for (unsigned j = 0; j < numParts; j++) {
			shapeArray->at(i).Parts.push_back(parts.ElementAt(j));
		}
		shapeArray->at(i).Vertices.reset(new vector<struct point3d>(numVerts));
		for (unsigned j = 0; j < numVerts; j++) {
			shapeArray->at(i).Vertices->at(j).x = vertices.ElementAt(j).x;
			shapeArray->at(i).Vertices->at(j).y = vertices.ElementAt(j).y;
			shapeArray->at(i).Vertices->at(j).z = vertices.ElementAt(j).z;
		}
	}
	_shapeArray = VI_ShapeArray(shapeArray, GetShapeExtents());
	_observable->AddObserver(this);
}

EnVistasGeometryPlugin::~EnVistasGeometryPlugin() {
	_observable->DeleteObserver(this);
}

VI_String EnVistasGeometryPlugin::GetFactoryRegistryName() {
	throw METHOD_FOR_VISTAS_ERROR;
}

VI_PluginType EnVistasGeometryPlugin::GetType() {
	throw METHOD_FOR_VISTAS_ERROR;
}

VI_String EnVistasGeometryPlugin::GetName() {
	throw METHOD_FOR_VISTAS_ERROR;
}

void EnVistasGeometryPlugin::Set( const VI_Path& path ) {
	throw NOT_YET_IMPLEMENTED_ERROR;
}

VI_DataType EnVistasGeometryPlugin::GetDataType() {
	throw METHOD_FOR_VISTAS_ERROR;
}

VI_String EnVistasGeometryPlugin::GetDataName() {
	throw METHOD_FOR_VISTAS_ERROR;
}

VI_Path EnVistasGeometryPlugin::GetPath() {
	boost::shared_lock<boost::shared_mutex> lk(_readWriteMutex);

	char pathBuffer[128];
	lstrcpy(pathBuffer, _envContext->pMapLayer->m_path);
	VI_Path result(pathBuffer);
	return result;
}

long EnVistasGeometryPlugin::GetDiskSize() {
	throw METHOD_FOR_VISTAS_ERROR;
}

long EnVistasGeometryPlugin::GetMemorySize() {
	throw METHOD_FOR_VISTAS_ERROR;
}

VI_SpatialInfo EnVistasGeometryPlugin::GetSpatialInfo() {
	throw METHOD_FOR_VISTAS_ERROR;
}

VI_TemporalInfo EnVistasGeometryPlugin::GetTemporalInfo() {
	throw METHOD_FOR_VISTAS_ERROR;
}

VI_StringList EnVistasGeometryPlugin::GetAttributes() {
	boost::shared_lock<boost::shared_mutex> lk(_readWriteMutex);
	const int numColumns = _envContext->pMapLayer->GetColCount();
	list<VI_String> attributes;
	for (int i=0; i<numColumns; i++) {
		attributes.push_back(VI_String(_envContext->pMapLayer->GetFieldLabel(i)));
	}
	return attributes;
}

VI_String EnVistasGeometryPlugin::GetAttributeLabel( const VI_String& attribute ) {
	boost::shared_lock<boost::shared_mutex> lk(_readWriteMutex);
	return attribute;
}

VI_AttributeStats EnVistasGeometryPlugin::GetAttributeStats( const VI_String& attribute ) {
	throw METHOD_FOR_VISTAS_ERROR;
}

bool EnVistasGeometryPlugin::HasStats() {
	throw METHOD_FOR_VISTAS_ERROR;
}

void EnVistasGeometryPlugin::CalculateStatistics() {
	throw METHOD_FOR_VISTAS_ERROR;
}

bool EnVistasGeometryPlugin::ValuesAreTemporal() {
	throw METHOD_FOR_VISTAS_ERROR;
}

int EnVistasGeometryPlugin::GetNumShapes() {
	boost::shared_lock<boost::shared_mutex> lk(_readWriteMutex);
	return GetPolyArraySize();

}

VI_ShapeArray EnVistasGeometryPlugin::GetShapeArray() {
	boost::shared_lock<boost::shared_mutex> lk(_readWriteMutex);
	return _shapeArray;
}

VI_Color EnVistasGeometryPlugin::ConvertToColor(const Bin& bin) const {
	const auto& colorRef = bin.m_color;
	return VI_Color((int)GetRValue(colorRef), (int)GetGValue(colorRef),
		(int)GetBValue(colorRef));
}

map<VI_ImmutableAbstract, VI_Color> EnVistasGeometryPlugin::ObtainValueColorMap(
	const VI_String& attribute )
{
	boost::shared_lock<boost::shared_mutex> lk(_readWriteMutex);
	map<VI_ImmutableAbstract, VI_Color> result;
	auto mutableMapLayer = const_cast<MapLayer*>(_envContext->pMapLayer);
	const int numBin = mutableMapLayer->GetBinCount(USE_ACTIVE_COL);
	for (int i=0; i<numBin; i++) {
		auto bin = _envContext->pMapLayer->GetBin(USE_ACTIVE_COL, i);
		auto color = ConvertToColor(bin);
		result[VI_ImmutableAbstract(bin.m_minVal)] = color;
	}
	return result;
}

map<VI_ImmutableAbstract, VI_String> EnVistasGeometryPlugin::ObtainValueLabelMap(
	const VI_String& attribute)
{
	boost::shared_lock<boost::shared_mutex> lk(_readWriteMutex);
	map<VI_ImmutableAbstract, VI_String> result;
	auto mutableMapLayer = const_cast<MapLayer*>(_envContext->pMapLayer);
	const int numBin = mutableMapLayer->GetBinCount(USE_ACTIVE_COL);
	for (int i=0; i<numBin; i++) {
		auto bin = _envContext->pMapLayer->GetBin(USE_ACTIVE_COL, i);
		result[VI_ImmutableAbstract(bin.m_minVal)] = VI_String(bin.m_label);
	}
	return result;
}

shared_ptr<vector<VI_ImmutableAbstract>> EnVistasGeometryPlugin::ObtainValues(
	const VI_String& attribute)
{
	boost::shared_lock<boost::shared_mutex> lk(_readWriteMutex);
	shared_ptr<vector<VI_ImmutableAbstract>> result(new vector<VI_ImmutableAbstract>());
	auto mutableMapLayer = const_cast<MapLayer*>(_envContext->pMapLayer);
	const int numBin = mutableMapLayer->GetBinCount(USE_ACTIVE_COL);
	for (int i=0; i<numBin; i++) {
		auto bin = _envContext->pMapLayer->GetBin(USE_ACTIVE_COL, i);
		result->push_back(VI_ImmutableAbstract(bin.m_minVal));
	}
	return result;
}

VI_Abstract::AbstractType EnVistasGeometryPlugin::GetDataTypeFromXML( const VI_String& attribute ) {
	boost::shared_lock<boost::shared_mutex> lk(_readWriteMutex);
	return GetDataTypeColumn(USE_ACTIVE_COL);

}

bool EnVistasGeometryPlugin::IsDataDiscrete( const VI_String& attribute ) {
	boost::shared_lock<boost::shared_mutex> lk(_readWriteMutex);
	TYPE dataType = _envContext->pMapLayer->GetFieldType(USE_ACTIVE_COL);
	switch(dataType) {
	case TYPE_INT:
	case TYPE_LONG:
	case TYPE_CHAR:
		return true;
	case TYPE_FLOAT:
		return false;
	default:
		throw runtime_error("Unsupported DataType");
		break;
	}
}

VI_ShapeDataPlugin::MinMaxColorArray EnVistasGeometryPlugin::GetMinMaxColorArray( const VI_String& attribute ) {
	throw METHOD_FOR_VISTAS_ERROR;
}

VI_ShapeDataPlugin::ColorLabelArray EnVistasGeometryPlugin::ObtainColorLabelArray( const VI_String& attribute ) {
	throw METHOD_FOR_VISTAS_ERROR;
}

shared_ptr<vector<VI_ImmutableAbstract>> EnVistasGeometryPlugin::GetAttributeArray(
	const VI_String& attribute )
{
	boost::shared_lock<boost::shared_mutex> lk(_readWriteMutex);
	auto dataType = GetDataTypeColumn(USE_ACTIVE_COL);
	shared_ptr<vector<VI_ImmutableAbstract>> result(new vector<VI_ImmutableAbstract>());
	unsigned numShapes = GetPolyArraySize();
	switch(dataType) {
	case VI_Abstract::VALUE_TYPE_INT:
		for (int i=0; i<numShapes; i++) {
			int buffer;
			_envContext->pMapLayer->GetData(i, _envContext->pMapLayer->m_activeField, buffer);
			result->push_back(VI_ImmutableAbstract(buffer));
		}
		break;
	default:
		break;
	}
	return result;
}

VI_Abstract::AbstractType EnVistasGeometryPlugin::GetAttributeDataType( const VI_String& attribute ) {
	boost::shared_lock<boost::shared_mutex> lk(_readWriteMutex);
	return GetDataTypeColumn(USE_ACTIVE_COL);
}

struct shpmainheader EnVistasGeometryPlugin::GetShpMainHeader() const {
	boost::shared_lock<boost::shared_mutex> lk(_readWriteMutex);
	return GetShapeExtents();

}

VI_Abstract::AbstractType EnVistasGeometryPlugin::GetDataTypeColumn(
	int column) const
{
	TYPE dataType = _envContext->pMapLayer->GetFieldType(column);
	switch(dataType) {
	case TYPE_INT:
	case TYPE_LONG:
		return VI_Abstract::VALUE_TYPE_INT;
	case TYPE_FLOAT:
		return VI_Abstract::VALUE_TYPE_DOUBLE;
	case TYPE_CHAR:
		return VI_Abstract::VALUE_TYPE_STRING;
	default:
		throw runtime_error("Unsupported DataType");
		break;
	}
}

int EnVistasGeometryPlugin::GetPolyArraySize() {
	return _envContext->pMapLayer->m_pPolyArray->GetCount();
}

struct shpmainheader EnVistasGeometryPlugin::GetShapeExtents() const {
	struct shpmainheader Returned;
	Returned.filecode = -1;
	Returned.filelength = -1;
	Returned.mmax = -1;
	Returned.mmin = -1;
	Returned.pad = -1;
	Returned.shapetype = 15;
	Returned.unused0 = -1;
	Returned.unused1 = -1;
	Returned.unused2 = -1;
	Returned.unused3 = -1;
	Returned.unused4 = -1;
	Returned.version = -1;
	float xmin, xmax, ymin, ymax, zmin, zmax;
	_envContext->pMapLayer->GetExtents(xmin, xmax, ymin, ymax);
	const_cast<MapLayer*>(_envContext->pMapLayer)->GetZExtents(zmin, zmax);
	Returned.xmin = xmin;
	Returned.ymin = ymin;
	Returned.zmin = zmin;
	Returned.xmax = xmax;
	Returned.ymax = ymax;
	Returned.zmax = zmax;
	return Returned;
}

shared_ptr<const vector<VI_ShapeDeltaDataPlugin::VI_ShapeDelta>>
	EnVistasGeometryPlugin::GetDeltaArray() const
{
	auto result = InitDynamicArray<VI_ShapeDeltaDataPlugin::VI_ShapeDelta>();
	auto deltas = _envContext->pDeltaArray;
	if (!deltas) {
		throw logic_error("EnvContext has no delta array.");
	}

	for (int i=0; i<deltas->GetSize(); i++) {
		auto& delta = GetDelta(deltas, i);
		if (!IsCurrentYear(delta) || !IsActiveColumn(delta)) {
			continue;
		}
		int oldValue, newValue;
		delta.oldValue.GetAsInt(oldValue);
		delta.newValue.GetAsInt(newValue);
		result->push_back(VI_ShapeDelta(delta.cell,
			VI_ImmutableAbstract(oldValue),
			VI_ImmutableAbstract(newValue)
		));
	}
	return result;
}

bool EnVistasGeometryPlugin::CheckTypeVDataAndMapLayer(const DELTA& delta) const {
	if (delta.newValue.GetType() != GetDataTypeColumn(delta.col)) {
		return false;
	} else {
		return true;
	}
}

bool EnVistasGeometryPlugin::IsActiveColumn(const DELTA& delta) const {
	return delta.cell == _envContext->pMapLayer->m_activeField;
}

bool EnVistasGeometryPlugin::IsCurrentYear(const DELTA& delta) const {
	return delta.year == _envContext->currentYear;
}

void EnVistasGeometryPlugin::Update(const VI_Observable* const observable) {
	auto context = dynamic_cast<const EnvContextObservable*>(observable);
	if (!context) {
		return;
	}

	_envContext = context->GetEnvContext();
}
<commit_msg>deal with MinMaxColor for continuous data type.<commit_after>#include "stdafx.h"
#include "EnVistasGeometryPlugin.h"
#include <stdexcept>
#include <EnvExtension.h>
#include <Maplayer.h>
#include <vector>
#include <boost/thread/locks.hpp>
#include "SHP3DUtility.h"
#include <EnvEngine/DeltaArray.h>
#include <EnvInterface.h>
#include "EnvContextObservable.h"

using std::vector;
using std::logic_error;
using std::runtime_error;
using std::map;
using std::shared_ptr;

// this is the most ridiculous build error...
wxEvtHandler::wxEvtHandler(const wxEvtHandler&) { }

static const VI_String METHOD_FOR_VISTAS_ERROR("This class is for interfacing with \
												ENVISION. Most method are not \
												implemented; they are for VISTAS.");

static const VI_String NOT_YET_IMPLEMENTED_ERROR("Not implemented yet. Talk to Vir\
												 about this.");

EnVistasGeometryPlugin::EnVistasGeometryPlugin(
	std::shared_ptr<EnvContextObservable>& observable)
{
	_observable = observable;
	_envContext = _observable->GetEnvContext();
	auto polyArray = _envContext->pMapLayer->m_pPolyArray;
	unsigned numShapes = polyArray->GetCount();
	shared_ptr<vector<VI_Shape>> shapeArray(new vector<VI_Shape>(numShapes));
	for (unsigned i = 0; i < numShapes; i++) {
		auto shape = polyArray->ElementAt(i);
		CDWordArray& parts = shape->m_vertexPartArray;
		auto numParts = parts.GetCount();
		VertexArray& vertices = shape->m_vertexArray;
		auto numVerts = vertices.GetCount();

		shapeArray->at(i).ShapeHeader.numparts = numParts;
		shapeArray->at(i).ShapeHeader.numpoints = numVerts;
		shapeArray->at(i).ShapeHeader.xmax = shape->m_xMax;
		shapeArray->at(i).ShapeHeader.xmin = shape->m_xMin;
		shapeArray->at(i).ShapeHeader.ymin = shape->m_yMin;
		shapeArray->at(i).ShapeHeader.ymax = shape->m_yMax;
		float zmin, zmax;
		shape->GetBoundingZ(zmin, zmax);
		shapeArray->at(i).ShapeHeader.zmin = zmin;
		shapeArray->at(i).ShapeHeader.zmax = zmax;
		shapeArray->at(i).ShapeType = 15;
		for (unsigned j = 0; j < numParts; j++) {
			shapeArray->at(i).Parts.push_back(parts.ElementAt(j));
		}
		shapeArray->at(i).Vertices.reset(new vector<struct point3d>(numVerts));
		for (unsigned j = 0; j < numVerts; j++) {
			shapeArray->at(i).Vertices->at(j).x = vertices.ElementAt(j).x;
			shapeArray->at(i).Vertices->at(j).y = vertices.ElementAt(j).y;
			shapeArray->at(i).Vertices->at(j).z = vertices.ElementAt(j).z;
		}
	}
	_shapeArray = VI_ShapeArray(shapeArray, GetShapeExtents());
	_observable->AddObserver(this);
}

EnVistasGeometryPlugin::~EnVistasGeometryPlugin() {
	_observable->DeleteObserver(this);
}

VI_String EnVistasGeometryPlugin::GetFactoryRegistryName() {
	throw METHOD_FOR_VISTAS_ERROR;
}

VI_PluginType EnVistasGeometryPlugin::GetType() {
	throw METHOD_FOR_VISTAS_ERROR;
}

VI_String EnVistasGeometryPlugin::GetName() {
	throw METHOD_FOR_VISTAS_ERROR;
}

void EnVistasGeometryPlugin::Set( const VI_Path& path ) {
	throw NOT_YET_IMPLEMENTED_ERROR;
}

VI_DataType EnVistasGeometryPlugin::GetDataType() {
	throw METHOD_FOR_VISTAS_ERROR;
}

VI_String EnVistasGeometryPlugin::GetDataName() {
	throw METHOD_FOR_VISTAS_ERROR;
}

VI_Path EnVistasGeometryPlugin::GetPath() {
	boost::shared_lock<boost::shared_mutex> lk(_readWriteMutex);

	char pathBuffer[128];
	lstrcpy(pathBuffer, _envContext->pMapLayer->m_path);
	VI_Path result(pathBuffer);
	return result;
}

long EnVistasGeometryPlugin::GetDiskSize() {
	throw METHOD_FOR_VISTAS_ERROR;
}

long EnVistasGeometryPlugin::GetMemorySize() {
	throw METHOD_FOR_VISTAS_ERROR;
}

VI_SpatialInfo EnVistasGeometryPlugin::GetSpatialInfo() {
	throw METHOD_FOR_VISTAS_ERROR;
}

VI_TemporalInfo EnVistasGeometryPlugin::GetTemporalInfo() {
	throw METHOD_FOR_VISTAS_ERROR;
}

VI_StringList EnVistasGeometryPlugin::GetAttributes() {
	boost::shared_lock<boost::shared_mutex> lk(_readWriteMutex);
	const int numColumns = _envContext->pMapLayer->GetColCount();
	list<VI_String> attributes;
	for (int i=0; i<numColumns; i++) {
		attributes.push_back(VI_String(_envContext->pMapLayer->GetFieldLabel(i)));
	}
	return attributes;
}

VI_String EnVistasGeometryPlugin::GetAttributeLabel( const VI_String& attribute ) {
	boost::shared_lock<boost::shared_mutex> lk(_readWriteMutex);
	return attribute;
}

VI_AttributeStats EnVistasGeometryPlugin::GetAttributeStats( const VI_String& attribute ) {
	throw METHOD_FOR_VISTAS_ERROR;
}

bool EnVistasGeometryPlugin::HasStats() {
	throw METHOD_FOR_VISTAS_ERROR;
}

void EnVistasGeometryPlugin::CalculateStatistics() {
	throw METHOD_FOR_VISTAS_ERROR;
}

bool EnVistasGeometryPlugin::ValuesAreTemporal() {
	throw METHOD_FOR_VISTAS_ERROR;
}

int EnVistasGeometryPlugin::GetNumShapes() {
	boost::shared_lock<boost::shared_mutex> lk(_readWriteMutex);
	return GetPolyArraySize();

}

VI_ShapeArray EnVistasGeometryPlugin::GetShapeArray() {
	boost::shared_lock<boost::shared_mutex> lk(_readWriteMutex);
	return _shapeArray;
}

VI_Color EnVistasGeometryPlugin::ConvertToColor(const Bin& bin) const {
	const auto& colorRef = bin.m_color;
	return VI_Color((int)GetRValue(colorRef), (int)GetGValue(colorRef),
		(int)GetBValue(colorRef));
}

map<VI_ImmutableAbstract, VI_Color> EnVistasGeometryPlugin::ObtainValueColorMap(
	const VI_String& attribute )
{
	boost::shared_lock<boost::shared_mutex> lk(_readWriteMutex);
	map<VI_ImmutableAbstract, VI_Color> result;
	auto mutableMapLayer = const_cast<MapLayer*>(_envContext->pMapLayer);
	const int numBin = mutableMapLayer->GetBinCount(USE_ACTIVE_COL);
	for (int i=0; i<numBin; i++) {
		auto bin = _envContext->pMapLayer->GetBin(USE_ACTIVE_COL, i);
		auto color = ConvertToColor(bin);
		result[VI_ImmutableAbstract(bin.m_minVal)] = color;
	}
	return result;
}

map<VI_ImmutableAbstract, VI_String> EnVistasGeometryPlugin::ObtainValueLabelMap(
	const VI_String& attribute)
{
	boost::shared_lock<boost::shared_mutex> lk(_readWriteMutex);
	map<VI_ImmutableAbstract, VI_String> result;
	auto mutableMapLayer = const_cast<MapLayer*>(_envContext->pMapLayer);
	const int numBin = mutableMapLayer->GetBinCount(USE_ACTIVE_COL);
	for (int i=0; i<numBin; i++) {
		auto bin = _envContext->pMapLayer->GetBin(USE_ACTIVE_COL, i);
		result[VI_ImmutableAbstract(bin.m_minVal)] = VI_String(bin.m_label);
	}
	return result;
}

shared_ptr<vector<VI_ImmutableAbstract>> EnVistasGeometryPlugin::ObtainValues(
	const VI_String& attribute)
{
	boost::shared_lock<boost::shared_mutex> lk(_readWriteMutex);
	shared_ptr<vector<VI_ImmutableAbstract>> result(new vector<VI_ImmutableAbstract>());
	auto mutableMapLayer = const_cast<MapLayer*>(_envContext->pMapLayer);
	const int numBin = mutableMapLayer->GetBinCount(USE_ACTIVE_COL);
	for (int i=0; i<numBin; i++) {
		auto bin = _envContext->pMapLayer->GetBin(USE_ACTIVE_COL, i);
		result->push_back(VI_ImmutableAbstract(bin.m_minVal));
	}
	return result;
}

VI_Abstract::AbstractType EnVistasGeometryPlugin::GetDataTypeFromXML( const VI_String& attribute ) {
	boost::shared_lock<boost::shared_mutex> lk(_readWriteMutex);
	return GetDataTypeColumn(USE_ACTIVE_COL);

}

bool EnVistasGeometryPlugin::IsDataDiscrete( const VI_String& attribute ) {
	boost::shared_lock<boost::shared_mutex> lk(_readWriteMutex);
	TYPE dataType = _envContext->pMapLayer->GetFieldType(USE_ACTIVE_COL);
	switch(dataType) {
	case TYPE_INT:
	case TYPE_LONG:
	case TYPE_CHAR:
		return true;
	case TYPE_FLOAT:
	case TYPE_DOUBLE:
		return false;
	default:
		throw runtime_error("Unsupported DataType");
		break;
	}
}

VI_ShapeDataPlugin::MinMaxColorArray EnVistasGeometryPlugin::GetMinMaxColorArray(
	const VI_String& attribute)
{
	boost::shared_lock<boost::shared_mutex> lk(_readWriteMutex);
	auto result = InitDynamicArray<VI_ShapeDataPlugin::MinMaxColor>();
	auto mutableMapLayer = const_cast<MapLayer*>(_envContext->pMapLayer);
	const int numBin = mutableMapLayer->GetBinCount(USE_ACTIVE_COL);
	for (int i=0; i<numBin; i++) {
		auto bin = _envContext->pMapLayer->GetBin(USE_ACTIVE_COL, i);
		auto color = ConvertToColor(bin);
		result->push_back(MinMaxColor(bin.m_minVal, bin.m_maxVal, color));
	}
	return result;
}

VI_ShapeDataPlugin::ColorLabelArray EnVistasGeometryPlugin::ObtainColorLabelArray( const VI_String& attribute ) {
	throw METHOD_FOR_VISTAS_ERROR;
}

shared_ptr<vector<VI_ImmutableAbstract>> EnVistasGeometryPlugin::GetAttributeArray(
	const VI_String& attribute )
{
	boost::shared_lock<boost::shared_mutex> lk(_readWriteMutex);
	auto dataType = GetDataTypeColumn(USE_ACTIVE_COL);
	shared_ptr<vector<VI_ImmutableAbstract>> result(new vector<VI_ImmutableAbstract>());
	unsigned numShapes = GetPolyArraySize();
	switch(dataType) {
	case VI_Abstract::VALUE_TYPE_INT:
		for (int i=0; i<numShapes; i++) {
			int buffer;
			_envContext->pMapLayer->GetData(i, _envContext->pMapLayer->m_activeField, buffer);
			result->push_back(VI_ImmutableAbstract(buffer));
		}
		break;
	default:
		break;
	}
	return result;
}

VI_Abstract::AbstractType EnVistasGeometryPlugin::GetAttributeDataType( const VI_String& attribute ) {
	boost::shared_lock<boost::shared_mutex> lk(_readWriteMutex);
	return GetDataTypeColumn(USE_ACTIVE_COL);
}

struct shpmainheader EnVistasGeometryPlugin::GetShpMainHeader() const {
	boost::shared_lock<boost::shared_mutex> lk(_readWriteMutex);
	return GetShapeExtents();

}

VI_Abstract::AbstractType EnVistasGeometryPlugin::GetDataTypeColumn(
	int column) const
{
	TYPE dataType = _envContext->pMapLayer->GetFieldType(column);
	switch(dataType) {
	case TYPE_INT:
	case TYPE_LONG:
		return VI_Abstract::VALUE_TYPE_INT;
	case TYPE_FLOAT:
		return VI_Abstract::VALUE_TYPE_DOUBLE;
	case TYPE_CHAR:
		return VI_Abstract::VALUE_TYPE_STRING;
	default:
		throw runtime_error("Unsupported DataType");
		break;
	}
}

int EnVistasGeometryPlugin::GetPolyArraySize() {
	return _envContext->pMapLayer->m_pPolyArray->GetCount();
}

struct shpmainheader EnVistasGeometryPlugin::GetShapeExtents() const {
	struct shpmainheader Returned;
	Returned.filecode = -1;
	Returned.filelength = -1;
	Returned.mmax = -1;
	Returned.mmin = -1;
	Returned.pad = -1;
	Returned.shapetype = 15;
	Returned.unused0 = -1;
	Returned.unused1 = -1;
	Returned.unused2 = -1;
	Returned.unused3 = -1;
	Returned.unused4 = -1;
	Returned.version = -1;
	float xmin, xmax, ymin, ymax, zmin, zmax;
	_envContext->pMapLayer->GetExtents(xmin, xmax, ymin, ymax);
	const_cast<MapLayer*>(_envContext->pMapLayer)->GetZExtents(zmin, zmax);
	Returned.xmin = xmin;
	Returned.ymin = ymin;
	Returned.zmin = zmin;
	Returned.xmax = xmax;
	Returned.ymax = ymax;
	Returned.zmax = zmax;
	return Returned;
}

shared_ptr<const vector<VI_ShapeDeltaDataPlugin::VI_ShapeDelta>>
	EnVistasGeometryPlugin::GetDeltaArray() const
{
	auto result = InitDynamicArray<VI_ShapeDeltaDataPlugin::VI_ShapeDelta>();
	auto deltas = _envContext->pDeltaArray;
	if (!deltas) {
		throw logic_error("EnvContext has no delta array.");
	}

	for (int i=0; i<deltas->GetSize(); i++) {
		auto& delta = GetDelta(deltas, i);
		if (!IsCurrentYear(delta) || !IsActiveColumn(delta)) {
			continue;
		}
		int oldValue, newValue;
		delta.oldValue.GetAsInt(oldValue);
		delta.newValue.GetAsInt(newValue);
		result->push_back(VI_ShapeDelta(delta.cell,
			VI_ImmutableAbstract(oldValue),
			VI_ImmutableAbstract(newValue)
		));
	}
	return result;
}

bool EnVistasGeometryPlugin::CheckTypeVDataAndMapLayer(const DELTA& delta) const {
	if (delta.newValue.GetType() != GetDataTypeColumn(delta.col)) {
		return false;
	} else {
		return true;
	}
}

bool EnVistasGeometryPlugin::IsActiveColumn(const DELTA& delta) const {
	return delta.cell == _envContext->pMapLayer->m_activeField;
}

bool EnVistasGeometryPlugin::IsCurrentYear(const DELTA& delta) const {
	return delta.year == _envContext->currentYear;
}

void EnVistasGeometryPlugin::Update(const VI_Observable* const observable) {
	auto context = dynamic_cast<const EnvContextObservable*>(observable);
	if (!context) {
		return;
	}

	_envContext = context->GetEnvContext();
}
<|endoftext|>


<commit_before>#include "Menu.h"
#include <imgui.h>

const char* Menu::getType()
{
	return "MENU";
}

void Menu::update(double delta)
{
	m_remainingTime -= delta;
}

void Menu::onGUI(ImGuiContext* context)
{
	ImGui::SetCurrentContext(context);

	if (m_remainingTime > 0)
	{
		ImVec2 pos = ImVec2(50,50);
		ImGui::SetNextWindowPos(pos);
		ImGui::Begin("", 0, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
			ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_ShowBorders |
			ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoTitleBar);
		ImGui::Text("TIME LEFT");
		ImGui::Text("  %.1lf", m_remainingTime);
		ImGui::Text("");
		ImGui::Text("  SCORE  ");
		ImGui::Text("   %d   ", m_score);
		ImGui::End();
	}
	else
	{
		ImVec2 pos = ImVec2(400, 170);
		ImGui::SetNextWindowPos(pos);
		ImGui::SetNextWindowSize(ImVec2(200, 200));
		ImGui::Begin("", 0, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
			ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_ShowBorders |
			ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoTitleBar);

		ImGui::SetCursorPos(ImVec2(60,80));
		ImGui::Text("TIME IS UP!");
		ImGui::SetCursorPos(ImVec2(60, 100));
		ImGui::Text("  YOU GOT  ");
		ImGui::SetCursorPos(ImVec2(60, 130));
		ImGui::Text("    %d   ", m_score);
		ImGui::End();
		//ImGui::BeginPopupModal("", 0, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
		//	ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_ShowBorders |
		//	ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoTitleBar);
	}
}

void Menu::addScore(int value)
{
	m_score += value;
}

double Menu::getTime()
{
	return m_remainingTime;
}
<commit_msg>Updated ImGui with Addons<commit_after>#include "Menu.h"
#include <imgui.h>

const char* Menu::getType()
{
	return "MENU";
}

void Menu::update(double delta)
{
	m_remainingTime -= delta;
}

void Menu::onGUI(ImGuiContext* context)
{
	ImGui::SetCurrentContext(context);

	if (m_remainingTime > 0)
	{
		ImVec2 pos = ImVec2(50,50);
		ImGui::SetNextWindowPos(pos);
		ImGui::Begin("", 0, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
			ImGuiWindowFlags_NoCollapse |
			ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoTitleBar);
		ImGui::Text("TIME LEFT");
		ImGui::Text("  %.1lf", m_remainingTime);
		ImGui::Text("");
		ImGui::Text("  SCORE  ");
		ImGui::Text("   %d   ", m_score);
		ImGui::End();
	}
	else
	{
		ImVec2 pos = ImVec2(400, 170);
		ImGui::SetNextWindowPos(pos);
		ImGui::SetNextWindowSize(ImVec2(200, 200));
		ImGui::Begin("", 0, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
			ImGuiWindowFlags_NoCollapse  |
			ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoTitleBar);

		ImGui::SetCursorPos(ImVec2(60,80));
		ImGui::Text("TIME IS UP!");
		ImGui::SetCursorPos(ImVec2(60, 100));
		ImGui::Text("  YOU GOT  ");
		ImGui::SetCursorPos(ImVec2(60, 130));
		ImGui::Text("    %d   ", m_score);
		ImGui::End();
		//ImGui::BeginPopupModal("", 0, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
		//	ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_ShowBorders |
		//	ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoTitleBar);
	}
}

void Menu::addScore(int value)
{
	m_score += value;
}

double Menu::getTime()
{
	return m_remainingTime;
}
<|endoftext|>


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

class Solution {
public:
    int findNthDigit(int n) {
        int digit_len = 1;
        while (n > digit_len * 9 * pow(10, digit_len - 1)) {
            n -= digit_len  * 9 * pow(10, digit_len - 1);
            ++digit_len;
        }

        const int num = pow(10, digit_len - 1) + (n - 1) / digit_len;

        int nth_digit = num / pow(10, (digit_len - 1) - (n - 1) % digit_len);
        nth_digit %= 10;

        return nth_digit;
    }
};
<commit_msg>Update nth-digit.cpp<commit_after>// Time:  O(logn)
// Space: O(1)

class Solution {
public:
    int findNthDigit(int n) {
        int digit_len = 1;
        while (n > digit_len * 9 * pow(10, digit_len - 1)) {
            n -= digit_len * 9 * pow(10, digit_len - 1);
            ++digit_len;
        }

        const int num = pow(10, digit_len - 1) + (n - 1) / digit_len;

        int nth_digit = num / pow(10, (digit_len - 1) - (n - 1) % digit_len);
        nth_digit %= 10;

        return nth_digit;
    }
};
<|endoftext|>


<commit_before>/*
 * ImageProcessing.cpp
 *
 * function: all image processing for one camera
 *
 * author: Jannik Beyerstedt
 */

#include "ImageProcessing.h"

#include "DataFormats.h"
#include "Logger.h"

#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>

#include <iostream>

//#define DEBUG
#define REFERENCE_FRAME_DELAY 60

ImageProcessing::ImageProcessing(int camID, ImageSource* src, CameraParams* cam, ObjectDetection* objDet, IntraSystemMessaging* intMsg)
    : cameraID(camID), capture(src), camParams(cam), objectDet(objDet), internalCom(intMsg) {
  LOG_SCOPE;

  /*
   * set reference frame for tracking
   */
  cv::Mat frame;

  std::cout << "camera " << camID << ": waiting for reference frame...\n" << std::flush;
  cv::namedWindow("reference frame", cv::WINDOW_AUTOSIZE);
  for (int i = 0; i < REFERENCE_FRAME_DELAY; i++) {
    *capture >> frame;

    imshow("reference frame", frame);
    if (cv::waitKey(1) >= 0) {
      break;
    }
  }
  objectDet->setReferenceFrame(frame);
  std::cout << "camera " << camID << ": reference frame set\n" << std::flush;
  cv::destroyWindow("reference frame");

  /*
   * initialize global frame mask
   */
  camParams->initGlobalMask(frame);
}

ImageProcessing::~ImageProcessing() {
  LOG_SCOPE;

  delete capture;
  delete camParams;
  delete objectDet;
  // do not delete messaging, because pointer is held by main!!!
}

void ImageProcessing::evaluate() {
  cv::Mat frame;
  Status status = OK;
  PxPosList pxPositions;
  VectRayList objectRayList;

  /*
   * image processing chain
   */
  *capture >> frame;

  camParams->addGlobalMaskToFrame(frame);

  status = objectDet->detect(frame, pxPositions);

#ifdef DEBUG
  PxPos pixelPos = pxPositions[0];
  if (status != ERR) {
    circle(frame, cv::Point(pixelPos.x, pixelPos.y), 20, cv::Scalar(255, 0, 0), 2);
    circle(frame, cv::Point(pixelPos.x, pixelPos.y), 24, cv::Scalar(0, 0, 0), 2);
  }
  imshow("tracking", frame);
#endif

  for (PxPos pixel : pxPositions) {
    PxPos undistorted;
    VectRay objectRay;

    camParams->undistort(pixel, undistorted);
    camParams->calcObjRay(undistorted, objectRay);

    objectRayList.push_back(objectRay);
  }

  /*
   * send data
   */
  IntraSysMsg message{cameraID, objectRayList, status};
  internalCom->send(message);
}
<commit_msg>[FIX] set reference frame with globalMask applied!! --> initGlobalMask before setting the referenceFrame, so that the referenceFrame can use the globalMask<commit_after>/*
 * ImageProcessing.cpp
 *
 * function: all image processing for one camera
 *
 * author: Jannik Beyerstedt
 */

#include "ImageProcessing.h"

#include "DataFormats.h"
#include "Logger.h"

#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>

#include <iostream>

//#define DEBUG
#define REFERENCE_FRAME_DELAY 60

ImageProcessing::ImageProcessing(int camID, ImageSource* src, CameraParams* cam, ObjectDetection* objDet, IntraSystemMessaging* intMsg)
    : cameraID(camID), capture(src), camParams(cam), objectDet(objDet), internalCom(intMsg) {
  LOG_SCOPE;

  cv::Mat frame;

  /*
   * initialize global frame mask
   */
  *capture >> frame;
  camParams->initGlobalMask(frame);

  /*
   * set reference frame for tracking
   */
  std::cout << "camera " << camID << ": waiting for reference frame...\n" << std::flush;
  cv::namedWindow("reference frame", cv::WINDOW_AUTOSIZE);
  for (int i = 0; i < REFERENCE_FRAME_DELAY; i++) {
    *capture >> frame;

    camParams->addGlobalMaskToFrame(frame);

    imshow("reference frame", frame);
    if (cv::waitKey(1) >= 0) {
      break;
    }
  }
  objectDet->setReferenceFrame(frame);
  std::cout << "camera " << camID << ": reference frame set\n" << std::flush;
  cv::destroyWindow("reference frame");
}

ImageProcessing::~ImageProcessing() {
  LOG_SCOPE;

  delete capture;
  delete camParams;
  delete objectDet;
  // do not delete messaging, because pointer is held by main!!!
}

void ImageProcessing::evaluate() {
  cv::Mat frame;
  Status status = OK;
  PxPosList pxPositions;
  VectRayList objectRayList;

  /*
   * image processing chain
   */
  *capture >> frame;

  camParams->addGlobalMaskToFrame(frame);

  status = objectDet->detect(frame, pxPositions);

#ifdef DEBUG
  PxPos pixelPos = pxPositions[0];
  if (status != ERR) {
    circle(frame, cv::Point(pixelPos.x, pixelPos.y), 20, cv::Scalar(255, 0, 0), 2);
    circle(frame, cv::Point(pixelPos.x, pixelPos.y), 24, cv::Scalar(0, 0, 0), 2);
  }
  imshow("tracking", frame);
#endif

  for (PxPos pixel : pxPositions) {
    PxPos undistorted;
    VectRay objectRay;

    camParams->undistort(pixel, undistorted);
    camParams->calcObjRay(undistorted, objectRay);

    objectRayList.push_back(objectRay);
  }

  /*
   * send data
   */
  IntraSysMsg message{cameraID, objectRayList, status};
  internalCom->send(message);
}
<|endoftext|>