<commit_before>#include <sstream>
#include <string>
#include "codegen.hpp"
//
//  NOTE: This file is autogenerated based on the tac-definition.
//        You should therefore not edit it manually.
//
using namespace std;
using namespace bohrium::core;

namespace bohrium{
namespace engine{
namespace cpu{
namespace codegen{

string Walker::oper_neutral_element(OPERATOR oper, ETYPE etype)
{
    switch(oper) {
        case ADD:               return "0";
        case MULTIPLY:          return "1";
        case MAXIMUM:
            switch(etype) {
                case BOOL:      return "0";
                case INT8:      return "INT8_MIN";
                case INT16:     return "INT16_MIN";
                case INT32:     return "INT32_MIN";
                case INT64:     return "INT64_MIN";
                case UINT8:     return "UINT8_MIN";
                case UINT16:    return "UINT16_MIN";
                case UINT32:    return "UINT32_MIN";
                case UINT64:    return "UINT64_MIN";
                case FLOAT32:   return "FLT_MIN";
                case FLOAT64:   return "DBL_MIN";
                default:        return "UNKNOWN_NEUTRAL_FOR_MAXIMUM_OF_GIVEN_TYPE";
            }
        case MINIMUM:
            switch(etype) {
                case BOOL:      return "1";
                case INT8:      return "INT8_MAX";
                case INT16:     return "INT16_MAX";
                case INT32:     return "INT32_MAX";
                case INT64:     return "INT64_MAX";
                case UINT8:     return "UINT8_MAX";
                case UINT16:    return "UINT16_MAX";
                case UINT32:    return "UINT32_MAX";
                case UINT64:    return "UINT64_MAX";
                case FLOAT32:   return "FLT_MAX";
                case FLOAT64:   return "DBL_MAX";
                default:        return "UNKNOWN_NEUTRAL_FOR_MINIMUM_OF_GIVEN_TYPE";
            }
        case LOGICAL_AND:       return "1";
        case LOGICAL_OR:        return "0";
        case LOGICAL_XOR:       return "0";
        case BITWISE_AND:       return "1";
            switch(etype) {
                case BOOL:      return "1";
                case INT8:      return "-1";
                case INT16:     return "-1";
                case INT32:     return "-1";
                case INT64:     return "-1";
                case UINT8:     return "UINT8_MAX";
                case UINT16:    return "UINT16_MAX";
                case UINT32:    return "UINT32_MAX";
                case UINT64:    return "UINT64_MAX";
                default:        return "UNKNOWN_NEUTRAL_FOR_BITWISE_AND_OF_GIVEN_TYPE";
            }
        case BITWISE_OR:        return "0";
        case BITWISE_XOR:       return "0";
        default:                return "UNKNOWN_NEUTRAL_FOR_OPERATOR";
    }
}

string Walker::oper_description(tac_t tac)
{
    stringstream ss;
    ss << operator_text(tac.oper) << " (";
    switch(core::tac_noperands(tac)) {
        case 3:
            ss << layout_text(kernel_.operand_glb(tac.out).meta().layout);
            ss << ", ";
            ss << layout_text(kernel_.operand_glb(tac.in1).meta().layout);
            ss << ", ";
            ss << layout_text(kernel_.operand_glb(tac.in2).meta().layout);
            break;
        case 2:
            ss << layout_text(kernel_.operand_glb(tac.out).meta().layout);
            ss << ", ";
            ss << layout_text(kernel_.operand_glb(tac.in1).meta().layout);
            break;
        case 1:
            ss << layout_text(kernel_.operand_glb(tac.out).meta().layout);
            break;
        default:
            break;
    }
    ss << ")";
    return ss.str();
}

string Walker::oper(OPERATOR oper, ETYPE etype, string in1, string in2)
{
    switch(oper) {
        case ABSOLUTE:
            switch(etype) {
                case COMPLEX128:    return _cabs(in1);
                case COMPLEX64:     return _cabsf(in1);
                default:            return _abs(in1);
            }
        case ADD:                   return _add(in1, in2);
        case ARCCOS:
            switch(etype) {
                case COMPLEX128:    return _cacos(in1);
                case COMPLEX64:     return _cacosf(in1);
                default:            return _acos(in1);
            }
        case ARCCOSH:
            switch(etype) {
                case COMPLEX128:    return _cacosh(in1);
                case COMPLEX64:     return _cacosf(in1);
                default:            return _acosh(in1);
            }
        case ARCSIN:
            switch(etype) {
                case COMPLEX128:    return _casin(in1);
                case COMPLEX64:     return _casinf(in1);
                default:            return _asin(in1);
            }
        case ARCSINH:
            switch(etype) {
                case COMPLEX128:    return _casinh(in1);
                case COMPLEX64:     return _casinhf(in1);
                default:            return _asinh(in1);
            }
        case ARCTAN:
            switch(etype) {
                case COMPLEX128:    return _catan(in1);
                case COMPLEX64:     return _catanf(in1);
                default:            return _atan(in1);
            }
        case ARCTAN2:               return _atan2(in1, in2);
        case ARCTANH:
            switch(etype) {
                case COMPLEX128:    return _catanh(in1);
                case COMPLEX64:     return _catanhf(in1);
                default:            return _atanh(in1);
            }
        case BITWISE_AND:           return _bitw_and(in1, in2);
        case BITWISE_OR:            return _bitw_or(in1, in2);
        case BITWISE_XOR:           return _bitw_xor(in1, in2);
        case CEIL:                  return _ceil(in1);
        case COS:
            switch(etype) {
                case COMPLEX128:    return _ccos(in1);
                case COMPLEX64:     return _ccosf(in1);
                default:            return _cos(in1);
            }
        case COSH:
            switch(etype) {
                case COMPLEX128:    return _ccosh(in1);
                case COMPLEX64:     return _ccoshf(in1);
                default:            return _cosh(in1);
            }
        case DISCARD:               break;  // TODO: Raise exception
        case DIVIDE:                return _div(in1, in2);
        case EQUAL:                 return _eq(in1, in2);
        case EXP:
            switch(etype) {
                case COMPLEX128:    return _cexp(in1);
                case COMPLEX64:     return _cexpf(in1);
                default:            return _exp(in1);
            }
        case EXP2:
            switch(etype) {
                case COMPLEX128:    return _cexp2(in1);
                case COMPLEX64:     return _cexp2f(in1);
                default:            return _exp2(in1);
            }
        case EXPM1:                 return _expm1(in1);
        case EXTENSION_OPERATOR:    break;  // TODO: Raise exception
        case FLOOD:                 break;  // TODO: Raise exception
        case FLOOR:                 return _floor(in1);
        case FREE:                  break;  // TODO: Raise exception
        case GREATER:               return _gt(in1, in2);
        case GREATER_EQUAL:         return _gteq(in1, in2);
        case IDENTITY:              return in1;
        case IMAG:
            switch(etype) {
                case FLOAT32:       return _cimagf(in1);
                default:            return _cimag(in1);
            }
        case INVERT:
            switch(etype) {
                case BOOL:          return _invertb(in1);
                default:            return _invert(in1);
            }
        case ISINF:                 return _isinf(in1);
        case ISNAN:                 return _isnan(in1);
        case LEFT_SHIFT:            return _bitw_leftshift(in1, in2);
        case LESS:                  return _lt(in1, in2);
        case LESS_EQUAL:            return _lteq(in1, in2);
        case LOG:
            switch(etype) {
                case COMPLEX128:    return _clog(in1);
                case COMPLEX64:     return _clogf(in1);
                default:            return _log(in1);
            }
        case LOG10:
            switch(etype) {
                case COMPLEX128:    return _clog10(in1);
                case COMPLEX64:     return _clog10f(in1);
                default:            return _log10(in1);
            }
        case LOG1P:                 return _log1p(in1);
        case LOG2:                  return _log2(in1);
        case LOGICAL_AND:           return _logic_and(in1, in2);
        case LOGICAL_NOT:           return _logic_not(in1);
        case LOGICAL_OR:            return _logic_or(in1, in2);
        case LOGICAL_XOR:           return _logic_xor(in1, in2);
        case MAXIMUM:               return _max(in1, in2);
        case MINIMUM:               return _min(in1, in2);
        case MOD:                   return _mod(in1, in2);
        case MULTIPLY:              return _mul(in1, in2);
        case NONE:                  break;  // TODO: Raise exception
        case NOT_EQUAL:             return _neq(in1, in2);
        case POWER:
            switch(etype) {
                case COMPLEX128:    return _cpow(in1, in2);
                case COMPLEX64:     return _cpowf(in1, in2);
                default:            return _pow(in1, in2);
            }
        case RANDOM:                return _random(in1, in2);
        case RANGE:                 return _range();
        case REAL:
            switch(etype) {
                case FLOAT32:       return _crealf(in1);
                default:            return _creal(in1);
            }
        case RIGHT_SHIFT:           return _bitw_rightshift(in1, in2);
        case RINT:                  return _rint(in1);
        case SIN:
            switch(etype) {
                case COMPLEX128:    return _csin(in1);
                case COMPLEX64:     return _csinf(in1);
                default:            return _sin(in1);
            }
        case SIGN:
            switch(etype) {
                case COMPLEX128:    return _div(in1, _cabs(in1));
                case COMPLEX64:     return _div(in1, _cabsf(in1));
                default:            return _sub(
                                            _parens(_gt(in1, "0")),
                                            _parens(_lt(in1, "0"))
                                           );
            }

        case SINH:
            switch(etype) {
                case COMPLEX128:    return _csinh(in1);
                case COMPLEX64:     return _csinhf(in1);
                default:            return _sinh(in1);
            }
        case SQRT:
            switch(etype) {
                case COMPLEX128:    return _csqrt(in1);
                case COMPLEX64:     return _csqrtf(in1);
                default:            return _sqrt(in1);
            }
        case SUBTRACT:              return _sub(in1, in2);
        case SYNC:                  break;  // TODO: Raise exception
        case TAN:
            switch(etype) {
                case COMPLEX128:    return _ctan(in1);
                case COMPLEX64:     return _ctanf(in1);
                default:            return _tan(in1);
            }
        case TANH:
            switch(etype) {
                case COMPLEX128:    return _ctanh(in1);
                case COMPLEX64:     return _ctanhf(in1);
                default:            return _tanh(in1);
            }
        case TRUNC:                 return _trunc(in1);
        default:                    return "NOT_IMPLEMENTED_YET";
    }
    return "NO NO< NO NO NO NO NONO NO NO NO NOTHERES NO LIMITS";
}

string Walker::synced_oper(OPERATOR operation, ETYPE etype, string out, string in1, string in2)
{
    stringstream ss;
    switch(operation) {
        case MAXIMUM:
        case MINIMUM:
        case LOGICAL_AND:
        case LOGICAL_OR:
        case LOGICAL_XOR:
            ss << _omp_critical(_assign(out, oper(operation, etype, in1, in2)), "accusync");
            break;
        default:
            switch(etype) {
                case COMPLEX64:
                case COMPLEX128:
                    ss << _omp_critical(_assign(out, oper(operation, etype, in1, in2)), "accusync");
                    break;
                default:
                    ss << _omp_atomic(_assign(out, oper(operation, etype, in1, in2)));
                    break;
            }
            break;
    }
    return ss.str();
}

}}}}
<commit_msg>cpu: Fixed csign(0).<commit_after>#include <sstream>
#include <string>
#include "codegen.hpp"
//
//  NOTE: This file is autogenerated based on the tac-definition.
//        You should therefore not edit it manually.
//
using namespace std;
using namespace bohrium::core;

namespace bohrium{
namespace engine{
namespace cpu{
namespace codegen{

string Walker::oper_neutral_element(OPERATOR oper, ETYPE etype)
{
    switch(oper) {
        case ADD:               return "0";
        case MULTIPLY:          return "1";
        case MAXIMUM:
            switch(etype) {
                case BOOL:      return "0";
                case INT8:      return "INT8_MIN";
                case INT16:     return "INT16_MIN";
                case INT32:     return "INT32_MIN";
                case INT64:     return "INT64_MIN";
                case UINT8:     return "UINT8_MIN";
                case UINT16:    return "UINT16_MIN";
                case UINT32:    return "UINT32_MIN";
                case UINT64:    return "UINT64_MIN";
                case FLOAT32:   return "FLT_MIN";
                case FLOAT64:   return "DBL_MIN";
                default:        return "UNKNOWN_NEUTRAL_FOR_MAXIMUM_OF_GIVEN_TYPE";
            }
        case MINIMUM:
            switch(etype) {
                case BOOL:      return "1";
                case INT8:      return "INT8_MAX";
                case INT16:     return "INT16_MAX";
                case INT32:     return "INT32_MAX";
                case INT64:     return "INT64_MAX";
                case UINT8:     return "UINT8_MAX";
                case UINT16:    return "UINT16_MAX";
                case UINT32:    return "UINT32_MAX";
                case UINT64:    return "UINT64_MAX";
                case FLOAT32:   return "FLT_MAX";
                case FLOAT64:   return "DBL_MAX";
                default:        return "UNKNOWN_NEUTRAL_FOR_MINIMUM_OF_GIVEN_TYPE";
            }
        case LOGICAL_AND:       return "1";
        case LOGICAL_OR:        return "0";
        case LOGICAL_XOR:       return "0";
        case BITWISE_AND:       return "1";
            switch(etype) {
                case BOOL:      return "1";
                case INT8:      return "-1";
                case INT16:     return "-1";
                case INT32:     return "-1";
                case INT64:     return "-1";
                case UINT8:     return "UINT8_MAX";
                case UINT16:    return "UINT16_MAX";
                case UINT32:    return "UINT32_MAX";
                case UINT64:    return "UINT64_MAX";
                default:        return "UNKNOWN_NEUTRAL_FOR_BITWISE_AND_OF_GIVEN_TYPE";
            }
        case BITWISE_OR:        return "0";
        case BITWISE_XOR:       return "0";
        default:                return "UNKNOWN_NEUTRAL_FOR_OPERATOR";
    }
}

string Walker::oper_description(tac_t tac)
{
    stringstream ss;
    ss << operator_text(tac.oper) << " (";
    switch(core::tac_noperands(tac)) {
        case 3:
            ss << layout_text(kernel_.operand_glb(tac.out).meta().layout);
            ss << ", ";
            ss << layout_text(kernel_.operand_glb(tac.in1).meta().layout);
            ss << ", ";
            ss << layout_text(kernel_.operand_glb(tac.in2).meta().layout);
            break;
        case 2:
            ss << layout_text(kernel_.operand_glb(tac.out).meta().layout);
            ss << ", ";
            ss << layout_text(kernel_.operand_glb(tac.in1).meta().layout);
            break;
        case 1:
            ss << layout_text(kernel_.operand_glb(tac.out).meta().layout);
            break;
        default:
            break;
    }
    ss << ")";
    return ss.str();
}

string Walker::oper(OPERATOR oper, ETYPE etype, string in1, string in2)
{
    switch(oper) {
        case ABSOLUTE:
            switch(etype) {
                case COMPLEX128:    return _cabs(in1);
                case COMPLEX64:     return _cabsf(in1);
                default:            return _abs(in1);
            }
        case ADD:                   return _add(in1, in2);
        case ARCCOS:
            switch(etype) {
                case COMPLEX128:    return _cacos(in1);
                case COMPLEX64:     return _cacosf(in1);
                default:            return _acos(in1);
            }
        case ARCCOSH:
            switch(etype) {
                case COMPLEX128:    return _cacosh(in1);
                case COMPLEX64:     return _cacosf(in1);
                default:            return _acosh(in1);
            }
        case ARCSIN:
            switch(etype) {
                case COMPLEX128:    return _casin(in1);
                case COMPLEX64:     return _casinf(in1);
                default:            return _asin(in1);
            }
        case ARCSINH:
            switch(etype) {
                case COMPLEX128:    return _casinh(in1);
                case COMPLEX64:     return _casinhf(in1);
                default:            return _asinh(in1);
            }
        case ARCTAN:
            switch(etype) {
                case COMPLEX128:    return _catan(in1);
                case COMPLEX64:     return _catanf(in1);
                default:            return _atan(in1);
            }
        case ARCTAN2:               return _atan2(in1, in2);
        case ARCTANH:
            switch(etype) {
                case COMPLEX128:    return _catanh(in1);
                case COMPLEX64:     return _catanhf(in1);
                default:            return _atanh(in1);
            }
        case BITWISE_AND:           return _bitw_and(in1, in2);
        case BITWISE_OR:            return _bitw_or(in1, in2);
        case BITWISE_XOR:           return _bitw_xor(in1, in2);
        case CEIL:                  return _ceil(in1);
        case COS:
            switch(etype) {
                case COMPLEX128:    return _ccos(in1);
                case COMPLEX64:     return _ccosf(in1);
                default:            return _cos(in1);
            }
        case COSH:
            switch(etype) {
                case COMPLEX128:    return _ccosh(in1);
                case COMPLEX64:     return _ccoshf(in1);
                default:            return _cosh(in1);
            }
        case DISCARD:               break;  // TODO: Raise exception
        case DIVIDE:                return _div(in1, in2);
        case EQUAL:                 return _eq(in1, in2);
        case EXP:
            switch(etype) {
                case COMPLEX128:    return _cexp(in1);
                case COMPLEX64:     return _cexpf(in1);
                default:            return _exp(in1);
            }
        case EXP2:
            switch(etype) {
                case COMPLEX128:    return _cexp2(in1);
                case COMPLEX64:     return _cexp2f(in1);
                default:            return _exp2(in1);
            }
        case EXPM1:                 return _expm1(in1);
        case EXTENSION_OPERATOR:    break;  // TODO: Raise exception
        case FLOOD:                 break;  // TODO: Raise exception
        case FLOOR:                 return _floor(in1);
        case FREE:                  break;  // TODO: Raise exception
        case GREATER:               return _gt(in1, in2);
        case GREATER_EQUAL:         return _gteq(in1, in2);
        case IDENTITY:              return in1;
        case IMAG:
            switch(etype) {
                case FLOAT32:       return _cimagf(in1);
                default:            return _cimag(in1);
            }
        case INVERT:
            switch(etype) {
                case BOOL:          return _invertb(in1);
                default:            return _invert(in1);
            }
        case ISINF:                 return _isinf(in1);
        case ISNAN:                 return _isnan(in1);
        case LEFT_SHIFT:            return _bitw_leftshift(in1, in2);
        case LESS:                  return _lt(in1, in2);
        case LESS_EQUAL:            return _lteq(in1, in2);
        case LOG:
            switch(etype) {
                case COMPLEX128:    return _clog(in1);
                case COMPLEX64:     return _clogf(in1);
                default:            return _log(in1);
            }
        case LOG10:
            switch(etype) {
                case COMPLEX128:    return _clog10(in1);
                case COMPLEX64:     return _clog10f(in1);
                default:            return _log10(in1);
            }
        case LOG1P:                 return _log1p(in1);
        case LOG2:                  return _log2(in1);
        case LOGICAL_AND:           return _logic_and(in1, in2);
        case LOGICAL_NOT:           return _logic_not(in1);
        case LOGICAL_OR:            return _logic_or(in1, in2);
        case LOGICAL_XOR:           return _logic_xor(in1, in2);
        case MAXIMUM:               return _max(in1, in2);
        case MINIMUM:               return _min(in1, in2);
        case MOD:                   return _mod(in1, in2);
        case MULTIPLY:              return _mul(in1, in2);
        case NONE:                  break;  // TODO: Raise exception
        case NOT_EQUAL:             return _neq(in1, in2);
        case POWER:
            switch(etype) {
                case COMPLEX128:    return _cpow(in1, in2);
                case COMPLEX64:     return _cpowf(in1, in2);
                default:            return _pow(in1, in2);
            }
        case RANDOM:                return _random(in1, in2);
        case RANGE:                 return _range();
        case REAL:
            switch(etype) {
                case FLOAT32:       return _crealf(in1);
                default:            return _creal(in1);
            }
        case RIGHT_SHIFT:           return _bitw_rightshift(in1, in2);
        case RINT:                  return _rint(in1);
        case SIN:
            switch(etype) {
                case COMPLEX128:    return _csin(in1);
                case COMPLEX64:     return _csinf(in1);
                default:            return _sin(in1);
            }
        case SIGN:
            switch(etype) {
                case COMPLEX128:    return _div(in1, _parens(_add(_cabs(in1), _parens(_eq(in1, "0")))));
                case COMPLEX64:     return _div(in1, _parens(_add(_cabsf(in1), _parens(_eq(in1, "0")))));
                default:            return _sub(
                                            _parens(_gt(in1, "0")),
                                            _parens(_lt(in1, "0"))
                                           );
            }

        case SINH:
            switch(etype) {
                case COMPLEX128:    return _csinh(in1);
                case COMPLEX64:     return _csinhf(in1);
                default:            return _sinh(in1);
            }
        case SQRT:
            switch(etype) {
                case COMPLEX128:    return _csqrt(in1);
                case COMPLEX64:     return _csqrtf(in1);
                default:            return _sqrt(in1);
            }
        case SUBTRACT:              return _sub(in1, in2);
        case SYNC:                  break;  // TODO: Raise exception
        case TAN:
            switch(etype) {
                case COMPLEX128:    return _ctan(in1);
                case COMPLEX64:     return _ctanf(in1);
                default:            return _tan(in1);
            }
        case TANH:
            switch(etype) {
                case COMPLEX128:    return _ctanh(in1);
                case COMPLEX64:     return _ctanhf(in1);
                default:            return _tanh(in1);
            }
        case TRUNC:                 return _trunc(in1);
        default:                    return "NOT_IMPLEMENTED_YET";
    }
    return "NO NO< NO NO NO NO NONO NO NO NO NOTHERES NO LIMITS";
}

string Walker::synced_oper(OPERATOR operation, ETYPE etype, string out, string in1, string in2)
{
    stringstream ss;
    switch(operation) {
        case MAXIMUM:
        case MINIMUM:
        case LOGICAL_AND:
        case LOGICAL_OR:
        case LOGICAL_XOR:
            ss << _omp_critical(_assign(out, oper(operation, etype, in1, in2)), "accusync");
            break;
        default:
            switch(etype) {
                case COMPLEX64:
                case COMPLEX128:
                    ss << _omp_critical(_assign(out, oper(operation, etype, in1, in2)), "accusync");
                    break;
                default:
                    ss << _omp_atomic(_assign(out, oper(operation, etype, in1, in2)));
                    break;
            }
            break;
    }
    return ss.str();
}

}}}}
<|endoftext|>


<commit_before>#pragma once

#include "../base/type.h"
#include "../base/check.h"
#include "../utils/type_traits.hpp"

#include <boost/callable_traits.hpp>
#include "../brigand.hpp"

#ifdef AUTOCXXPY_INCLUDED_PYBIND11
#include <pybind11/stl.h>
#endif

#include <iostream>
#include <type_traits>

#include "./utils.hpp"
#include <functional>

namespace c2py
{
    template <class method_constant, class ret_t, class base_t, class ... Ls, class ... Rs>
    inline constexpr auto wrap_pointer_argument_as_inout_impl(brigand::list<Ls...>, brigand::list <Rs...>)
    {
        namespace ct = boost::callable_traits;
        return [](Ls ... ls, base_t &arg, Rs ... rs)
        {
            constexpr auto method = method_constant::value;
            //using func_t = ct::function_type_t<decltype(method)>;
            //using args_t = ct::args_t<func_t, list>;
            //using ret_t = ct::return_type_t<func_t>;
            auto stdmethod = std::function<ct::function_type_t<decltype(method)>>(method);
            if constexpr (std::is_void_v<ret_t>)
            {
                stdmethod(std::forward<Ls>(ls)..., &arg, std::forward<Rs>(rs)...);
                return std::move(arg);
            }
            else
            {
                return append_as_tuple(stdmethod(
                    std::forward<Ls>(ls)...,
                    &arg,
                    std::forward<Rs>(rs)...
                ), std::move(arg));
            }
        };
    }
    template <class method_constant, class ret_t, class base_t, class ... Ls, class ... Rs>
    inline constexpr auto wrap_reference_argument_as_inout_impl(brigand::list<Ls...>, brigand::list <Rs...>)
    {
        namespace ct = boost::callable_traits;
        return [](Ls ... ls, base_t arg, Rs ... rs)
        {
            constexpr auto method = method_constant::value;
            auto stdmethod = std::function<ct::function_type_t<decltype(method)>>(method);
            if constexpr (std::is_void_v<ret_t>)
            {
                stdmethod(std::forward<Ls>(ls)..., arg, std::forward<Rs>(rs)...);
                return arg;
            }
            else
            {
                return append_as_tuple(stdmethod(
                    std::forward<Ls>(ls)...,
                    arg,
                    std::forward<Rs>(rs)...
                ), arg);

            }
        };
    }

    template <class method_constant, size_t index>
    inline constexpr auto wrap_argument_as_inout()
    {
        using namespace brigand;
        namespace ct = boost::callable_traits;

        constexpr auto method = method_constant::value;
        using func_t = ct::function_type_t<decltype(method)>;
        using args_t = ct::args_t<func_t, list>;

        if constexpr (check_not_out_of_bound<index, size<args_t>::value>())
        {
            using s = split_at<args_t, std::integral_constant<int, index>>;
            using ls = front<s>;
            using rs = pop_front<back<s>>;
            using arg_t = at<args_t, std::integral_constant<int, index>>;
            using ret_t = ct::return_type_t<func_t>;
            if constexpr (std::is_pointer_v<arg_t>)
            {
                using base_t = std::remove_pointer_t<arg_t>;
                return wrap_pointer_argument_as_inout_impl<method_constant, ret_t, base_t>(ls{}, rs{});
            }
            else
            {
                using base_t = std::remove_reference_t<arg_t>;
                return wrap_reference_argument_as_inout_impl<method_constant, ret_t, base_t>(ls{}, rs{});
            }
        }
    }

    template <class method_constant, class integral_constant>
    struct inout_argument_transform
    {
        using type = inout_argument_transform;
        using value_type = decltype(wrap_argument_as_inout<method_constant, integral_constant::value>());
        static constexpr value_type value = wrap_argument_as_inout<method_constant, integral_constant::value>();
    };
}
<commit_msg>Delete inout_argument.hpp<commit_after><|endoftext|>


<commit_before>/*
 * #%L
 * %%
 * Copyright (C) 2017 BMW Car IT GmbH
 * %%
 * 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.
 * #L%
 */
#include <string>
#include <unordered_map>
#include <numeric>

#include <gtest/gtest.h>

#include "libjoynrclustercontroller/access-control/RadixTree.h"

class RadixTreeTest : public ::testing::Test
{
public:
    RadixTreeTest()
    {
        /*
         * the tree has the following internal structure:
         *
         *                "" (root)
         *                 |
         *                 01 (i)
         *           ______|______
         *          /             \
         *         2               3
         *                      ___|___
         *                     /       \
         *                    4         7
         *                 ___|___
         *                /       \
         *               5         6
         *
         * '(i)' depicts an internal node
         */
        data["012"] = "2";
        data["013"] = "3";
        data["0134"] = "4";
        data["01345"] = "5";
        data["01346"] = "6";
        data["0137"] = "7";

        for (auto& entry : data) {
            tree.insert(entry.first, entry.second);
        }
    }

protected:
    void validateParents(const std::string& key, const std::vector<std::string>& expectedParents)
    {
        Node* node = tree.longestMatch(key);
        ASSERT_TRUE(node);
        auto parents = node->parents();
        auto expectedIt = expectedParents.begin();
        for (auto parentIt = parents.begin(); parentIt != parents.end(); ++parentIt) {
            ASSERT_NE(expectedIt, expectedParents.end());
            Node* parentNode = *parentIt;
            EXPECT_EQ(*expectedIt, parentNode->getValue());
            ++expectedIt;
        }
    }

    using Tree = joynr::RadixTree<std::string, std::string>;
    using Node = typename Tree::Node;
    Tree tree;
    std::unordered_map<std::string, std::string> data;
};

TEST_F(RadixTreeTest, insertReturnsNode)
{
    const std::string key = "key";
    const std::string value = "value";
    Node* node = tree.insert(key, value);

    EXPECT_EQ(value, node->getValue());
}

TEST_F(RadixTreeTest, insertReturnsNodeWithEmptyKey)
{
    const std::string key = "";
    const std::string value = "value";
    Node* node = tree.insert(key, value);

    EXPECT_EQ(value, node->getValue());
}

TEST_F(RadixTreeTest, longestMatchRetrievesCorrectValues)
{
    // find the entries by their original key
    for (auto& entry : data) {
        Node* node = tree.longestMatch(entry.first);
        ASSERT_TRUE(node) << "queried value (entry.first): " << entry.first;
        EXPECT_EQ(entry.second, node->getValue());
    }

    // add some more characters to each key
    // then retrieve the corresponding entry
    for (auto& entry : data) {
        Node* node = tree.longestMatch(entry.first + "####");
        ASSERT_TRUE(node);
        EXPECT_EQ(entry.second, node->getValue());
    }
}

TEST_F(RadixTreeTest, longestMatchDoesNotFindEntryForNonExistingKey)
{
    Node* node = tree.longestMatch("non-existing-key");
    EXPECT_FALSE(node);
}

TEST_F(RadixTreeTest, longestMatchDoesNotFindEntryForInternalNodeKey)
{
    Node* node = tree.longestMatch("01");
    EXPECT_FALSE(node);
}

TEST_F(RadixTreeTest, parentsAreValidWithRootValue)
{
    tree.insert(std::string(""), "root");
    validateParents("01346", {"4", "3", "root"});
    validateParents("01345", {"4", "3", "root"});
    validateParents("0134", {"3", "root"});
    validateParents("0137", {"3", "root"});
    validateParents("013", {"root"});
    validateParents("012", {"root"});
}

TEST_F(RadixTreeTest, parentsAreValidWithoutRootValue)
{
    validateParents("01346", {"4", "3"});
    validateParents("01345", {"4", "3"});
    validateParents("0134", {"3"});
    validateParents("0137", {"3"});
    validateParents("013", {});
    validateParents("012", {});
}

TEST_F(RadixTreeTest, eraseLeaf)
{
    const std::string leafKey = "0137";
    Node* leaf = tree.longestMatch(leafKey);
    ASSERT_TRUE(leaf);
    ASSERT_EQ("7", leaf->getValue());
    leaf->erase();
    Node* node = tree.longestMatch(leafKey);
    ASSERT_EQ("3", node->getValue());
}

TEST_F(RadixTreeTest, eraseMidNodeRestructuresTree)
{
    const std::string midNodeKey = "013";
    Node* midNode = tree.longestMatch(midNodeKey);
    ASSERT_TRUE(midNode);
    midNode->erase();
    Node* node = tree.longestMatch(midNodeKey);
    EXPECT_FALSE(node);

    validateParents("01346", {"4"});
    validateParents("01345", {"4"});
    validateParents("0134", {});
    validateParents("0137", {});
}

TEST_F(RadixTreeTest, eraseRoot)
{
    const std::string rootKey = "";
    tree.insert(rootKey, "root");

    Node* rootNode = tree.longestMatch(rootKey);
    ASSERT_TRUE(rootNode);
    rootNode->erase();
    Node* node = tree.longestMatch(rootKey);
    EXPECT_FALSE(node);

    validateParents("01346", {"4", "3"});
    validateParents("01345", {"4", "3"});
    validateParents("0134", {"3"});
    validateParents("0137", {"3"});
    validateParents("013", {});
    validateParents("012", {});
}

TEST_F(RadixTreeTest, callParentsOnRoot)
{
    const std::string rootKey = "";
    tree.insert(rootKey, "root");
    Node* rootNode = tree.longestMatch(rootKey);
    ASSERT_TRUE(rootNode);
    auto parents = rootNode->parents();
    EXPECT_EQ(parents.begin(), parents.end());
}

TEST_F(RadixTreeTest, visit)
{
    std::size_t nodeCount = 0;
    auto fun = [&nodeCount, data = data ](const auto& node, const auto& keyVector)
    {
        const std::string key = std::accumulate(keyVector.begin(), keyVector.end(), std::string(),  [](std::string& s, const auto& i) {
                return s+i.get();
              });
        ASSERT_EQ(data.at(key), node.getValue());
        nodeCount++;
    };
    tree.visit(fun);
    EXPECT_EQ(nodeCount, data.size());
}
<commit_msg>[C++] Added RadixTreeTest to check longestMatch() does not return wrong node<commit_after>/*
 * #%L
 * %%
 * Copyright (C) 2017 BMW Car IT GmbH
 * %%
 * 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.
 * #L%
 */
#include <string>
#include <unordered_map>
#include <numeric>

#include <gtest/gtest.h>

#include "libjoynrclustercontroller/access-control/RadixTree.h"

class RadixTreeTest : public ::testing::Test
{
public:
    RadixTreeTest()
    {
        /*
         * the tree has the following internal structure:
         *
         *                "" (root)
         *                 |
         *                 01 (i)
         *           ______|______
         *          /             \
         *         2               3
         *                      ___|___
         *                     /       \
         *                    4         7
         *                 ___|___
         *                /       \
         *               5         6
         *
         * '(i)' depicts an internal node
         */
        data["012"] = "2";
        data["013"] = "3";
        data["0134"] = "4";
        data["01345"] = "5";
        data["01346"] = "6";
        data["0137"] = "7";

        for (auto& entry : data) {
            tree.insert(entry.first, entry.second);
        }
    }

protected:
    void validateParents(const std::string& key, const std::vector<std::string>& expectedParents)
    {
        Node* node = tree.longestMatch(key);
        ASSERT_TRUE(node);
        auto parents = node->parents();
        auto expectedIt = expectedParents.begin();
        for (auto parentIt = parents.begin(); parentIt != parents.end(); ++parentIt) {
            ASSERT_NE(expectedIt, expectedParents.end());
            Node* parentNode = *parentIt;
            EXPECT_EQ(*expectedIt, parentNode->getValue());
            ++expectedIt;
        }
    }

    using Tree = joynr::RadixTree<std::string, std::string>;
    using Node = typename Tree::Node;
    Tree tree;
    std::unordered_map<std::string, std::string> data;
};

TEST_F(RadixTreeTest, insertReturnsNode)
{
    const std::string key = "key";
    const std::string value = "value";
    Node* node = tree.insert(key, value);

    EXPECT_EQ(value, node->getValue());
}

TEST_F(RadixTreeTest, insertReturnsNodeWithEmptyKey)
{
    const std::string key = "";
    const std::string value = "value";
    Node* node = tree.insert(key, value);

    EXPECT_EQ(value, node->getValue());
}

TEST_F(RadixTreeTest, longestMatchRetrievesCorrectValues)
{
    // find the entries by their original key
    for (auto& entry : data) {
        Node* node = tree.longestMatch(entry.first);
        ASSERT_TRUE(node) << "queried value (entry.first): " << entry.first;
        EXPECT_EQ(entry.second, node->getValue());
    }

    // add some more characters to each key
    // then retrieve the corresponding entry
    for (auto& entry : data) {
        Node* node = tree.longestMatch(entry.first + "####");
        ASSERT_TRUE(node);
        EXPECT_EQ(entry.second, node->getValue());
    }
}

TEST_F(RadixTreeTest, longestMatchDoesNotFindEntryForNonExistingKey)
{
    Node* node = tree.longestMatch("non-existing-key");
    EXPECT_FALSE(node);
}

TEST_F(RadixTreeTest, longestMatchDoesNotFindEntryForInternalNodeKey)
{
    Node* node = tree.longestMatch("01");
    EXPECT_FALSE(node);
}

TEST(RadixTreeTest2, longestMatchDoesNotReturnNonPrefixEntry)
{
    using Tree = joynr::RadixTree<std::string, std::string>;
    using Node = typename Tree::Node;
    Tree longestMatchTestTree;

    const std::string rootKey = "";
    longestMatchTestTree.insert(rootKey, "rootvalue");
    const std::string secondKey = "abc";
    longestMatchTestTree.insert(secondKey, "value1");

    const std::string searchKey = "abxyz";
    Node* resultNode = longestMatchTestTree.longestMatch(searchKey);
    EXPECT_EQ(resultNode->getKey(), rootKey);
}

TEST_F(RadixTreeTest, parentsAreValidWithRootValue)
{
    tree.insert(std::string(""), "root");
    validateParents("01346", {"4", "3", "root"});
    validateParents("01345", {"4", "3", "root"});
    validateParents("0134", {"3", "root"});
    validateParents("0137", {"3", "root"});
    validateParents("013", {"root"});
    validateParents("012", {"root"});
}

TEST_F(RadixTreeTest, parentsAreValidWithoutRootValue)
{
    validateParents("01346", {"4", "3"});
    validateParents("01345", {"4", "3"});
    validateParents("0134", {"3"});
    validateParents("0137", {"3"});
    validateParents("013", {});
    validateParents("012", {});
}

TEST_F(RadixTreeTest, eraseLeaf)
{
    const std::string leafKey = "0137";
    Node* leaf = tree.longestMatch(leafKey);
    ASSERT_TRUE(leaf);
    ASSERT_EQ("7", leaf->getValue());
    leaf->erase();
    Node* node = tree.longestMatch(leafKey);
    ASSERT_EQ("3", node->getValue());
}

TEST_F(RadixTreeTest, eraseMidNodeRestructuresTree)
{
    const std::string midNodeKey = "013";
    Node* midNode = tree.longestMatch(midNodeKey);
    ASSERT_TRUE(midNode);
    midNode->erase();
    Node* node = tree.longestMatch(midNodeKey);
    EXPECT_FALSE(node);

    validateParents("01346", {"4"});
    validateParents("01345", {"4"});
    validateParents("0134", {});
    validateParents("0137", {});
}

TEST_F(RadixTreeTest, eraseRoot)
{
    const std::string rootKey = "";
    tree.insert(rootKey, "root");

    Node* rootNode = tree.longestMatch(rootKey);
    ASSERT_TRUE(rootNode);
    rootNode->erase();
    Node* node = tree.longestMatch(rootKey);
    EXPECT_FALSE(node);

    validateParents("01346", {"4", "3"});
    validateParents("01345", {"4", "3"});
    validateParents("0134", {"3"});
    validateParents("0137", {"3"});
    validateParents("013", {});
    validateParents("012", {});
}

TEST_F(RadixTreeTest, callParentsOnRoot)
{
    const std::string rootKey = "";
    tree.insert(rootKey, "root");
    Node* rootNode = tree.longestMatch(rootKey);
    ASSERT_TRUE(rootNode);
    auto parents = rootNode->parents();
    EXPECT_EQ(parents.begin(), parents.end());
}

TEST_F(RadixTreeTest, visit)
{
    std::size_t nodeCount = 0;
    auto fun = [&nodeCount, data = data ](const auto& node, const auto& keyVector)
    {
        const std::string key = std::accumulate(keyVector.begin(), keyVector.end(), std::string(),  [](std::string& s, const auto& i) {
                return s+i.get();
              });
        ASSERT_EQ(data.at(key), node.getValue());
        nodeCount++;
    };
    tree.visit(fun);
    EXPECT_EQ(nodeCount, data.size());
}
<|endoftext|>


<commit_before>#include "test_precomp.hpp"

using namespace cv;
using namespace std;

TEST(Core_Drawing, _914)
{
    const int rows = 256;
    const int cols = 256;

    Mat img(rows, cols, CV_8UC1, Scalar(255));

    line(img, Point(0, 10), Point(255, 10), Scalar(0), 2, 4);
    line(img, Point(-5, 20), Point(260, 20), Scalar(0), 2, 4);
    line(img, Point(10, 0), Point(10, 255), Scalar(0), 2, 4);

    double x0 = 0.0/pow(2.0, -2.0);
    double x1 = 255.0/pow(2.0, -2.0);
    double y = 30.5/pow(2.0, -2.0);

    line(img, Point(int(x0), int(y)), Point(int(x1), int(y)), Scalar(0), 2, 4, 2);

    int pixelsDrawn = rows*cols - countNonZero(img);
    ASSERT_EQ( (3*rows + cols)*3 - 3*9, pixelsDrawn);
}

TEST(Core_OutputArraySreate, _1997)
{
    struct local {
        static void create(OutputArray arr, Size submatSize, int type)
        {
            int sizes[] = {submatSize.width, submatSize.height};
            arr.create(sizeof(sizes)/sizeof(sizes[0]), sizes, type);
        }
    };

    Mat mat(Size(512, 512), CV_8U);
    Size submatSize = Size(256, 256);

    ASSERT_NO_THROW(local::create( mat(Rect(Point(), submatSize)), submatSize, mat.type() ));
}<commit_msg>Added a test that documents that negative numbers are not clipped by cv::saturate_cast<commit_after>#include "test_precomp.hpp"

using namespace cv;
using namespace std;

TEST(Core_Drawing, _914)
{
    const int rows = 256;
    const int cols = 256;

    Mat img(rows, cols, CV_8UC1, Scalar(255));

    line(img, Point(0, 10), Point(255, 10), Scalar(0), 2, 4);
    line(img, Point(-5, 20), Point(260, 20), Scalar(0), 2, 4);
    line(img, Point(10, 0), Point(10, 255), Scalar(0), 2, 4);

    double x0 = 0.0/pow(2.0, -2.0);
    double x1 = 255.0/pow(2.0, -2.0);
    double y = 30.5/pow(2.0, -2.0);

    line(img, Point(int(x0), int(y)), Point(int(x1), int(y)), Scalar(0), 2, 4, 2);

    int pixelsDrawn = rows*cols - countNonZero(img);
    ASSERT_EQ( (3*rows + cols)*3 - 3*9, pixelsDrawn);
}

TEST(Core_OutputArraySreate, _1997)
{
    struct local {
        static void create(OutputArray arr, Size submatSize, int type)
        {
            int sizes[] = {submatSize.width, submatSize.height};
            arr.create(sizeof(sizes)/sizeof(sizes[0]), sizes, type);
        }
    };

    Mat mat(Size(512, 512), CV_8U);
    Size submatSize = Size(256, 256);

    ASSERT_NO_THROW(local::create( mat(Rect(Point(), submatSize)), submatSize, mat.type() ));
}

TEST(Core_SaturateCast, NegativeNotClipped)
{
    double d = -1.0;
    unsigned int val = cv::saturate_cast<unsigned int>(d);

    ASSERT_EQ(0xffffffff, val);
}
<|endoftext|>


<commit_before>#include <GL/glut.h>
#include <stdio.h>
#include <vector>
#include <floppy.h>
using namespace std;

vector<char> inputKey;
double g,v,tmp2;
int cnt;

void gameoverAnimation()
{

	inputKey.push_back('U');
	v=1.0;

}

void movePhysics()
{
int ii;
g=10;
for(ii=0;ii<inputKey.size();ii++)
	{

		if(inputKey[ii]=='U')
			{
				if((movementY+(resY/2)+50)<resY)
				movementY+=4;
				cnt++;
			}
		if(cnt>=7)
			{
				cnt=0;
				inputKey.erase(inputKey.begin()+ii);
			}

	}
//...GRAVITY
if(inputKey.size()==0)
{
// 0.021125
if(gameover==0)
{
tmp2=resY/2;
v=0.61+(abs(movementY)/tmp2)/6;
}
else
{
	if( (inputKey.size()==0 ) && (movementY <- (resY/2) ) )
	{
		gameover=0;
		resetFunc();
	}
}
movementY-= v*v/2*g;
}

}

void processSpecialKeys(int key, int xx, int yy)
{
	switch (key)
	{
		case GLUT_KEY_UP :
			if(gameover==0)
			inputKey.push_back('U');
			break;
	}
}
<commit_msg>tweaked movements<commit_after>#include <GL/glut.h>
#include <stdio.h>
#include <vector>
#include <floppy.h>
using namespace std;

vector<char> inputKey;
double g,v,tmp2;
int cnt;

void gameoverAnimation()
{

	inputKey.push_back('U');
	v=1.1;

}

void movePhysics()
{
int ii;
g=10;
for(ii=0;ii<inputKey.size();ii++)
	{

		if(inputKey[ii]=='U')
			{
				if((movementY+(resY/2)+50)<resY)
				movementY+=4;
				cnt++;
			}
		if(cnt>=7)
			{
				cnt=0;
				inputKey.erase(inputKey.begin()+ii);
			}

	}
//...GRAVITY
if(inputKey.size()==0)
{
// 0.021125
if(gameover==0)
{
tmp2=resY/2;
v=0.65+(abs(movementY)/tmp2)/5;
}
else
{
	if( (inputKey.size()==0 ) && (movementY <- (resY/2) ) )
	{
		gameover=0;
		resetFunc();
	}
}
movementY-= v*v/2*g;
}

}

void processSpecialKeys(int key, int xx, int yy)
{
	switch (key)
	{
		case GLUT_KEY_UP :
			if(gameover==0)
			inputKey.push_back('U');
			break;
	}
}
<|endoftext|>


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

#ifndef DUNE_HDD_EXAMPLES_LINEARELLIPTIC_OS2014_HH
#define DUNE_HDD_EXAMPLES_LINEARELLIPTIC_OS2014_HH

#define DUNE_HDD_LINEARELLIPTIC_TESTCASES_BASE_DISABLE_WARNING

#include <boost/numeric/conversion/cast.hpp>

#include <dune/fem/misc/mpimanager.hh>

#include <dune/stuff/common/logging.hh>
#include <dune/stuff/functions/expression.hh>

#include <dune/pymor/parameters/base.hh>

#include <dune/gdt/discretefunction/default.hh>
#include <dune/gdt/operators/projections.hh>
#include <dune/gdt/operators/prolongations.hh>
#include <dune/gdt/playground/products/elliptic-swipdg.hh>

#include <dune/hdd/linearelliptic/testcases/spe10.hh>
#include <dune/hdd/linearelliptic/discretizations/block-swipdg.hh>
#include <dune/hdd/linearelliptic/estimators/block-swipdg.hh>

namespace internal {

class Initializer
{
public:
  Initializer(const ssize_t info_log_levels,
              const ssize_t debug_log_levels,
              const bool enable_warnings,
              const bool enable_colors,
              const std::string info_color,
              const std::string debug_color,
              const std::string warn_color)
  {
    try {
      int argc = 0;
      char** argv = new char* [0];
      Dune::Fem::MPIManager::initialize(argc, argv);
    } catch (...) {}
    DSC::TimedLogger().create(info_log_levels,
                              debug_log_levels,
                              enable_warnings,
                              enable_colors,
                              info_color,
                              debug_color,
                              warn_color);
    DSC::TimedLogger().get("OS2014.spe10model1example").info() << "creating grid and problem... " << std::endl;
  }
}; // class Initializer

} // namespace internal

template< class GridType >
class OS2014Spe10Model1Example
  : internal::Initializer
{
  static_assert(GridType::dimension == 2, "Only available in 2d!");
public:
  typedef Dune::HDD::LinearElliptic::TestCases::Spe10::ParametricBlockModel1< GridType > TestCaseType;
  typedef double RangeFieldType;
  typedef Dune::HDD::LinearElliptic::Discretizations::BlockSWIPDG< GridType, RangeFieldType, 1 > DiscretizationType;
  typedef typename DiscretizationType::VectorType VectorType;

private:
  typedef Dune::HDD::LinearElliptic::Estimators::BlockSWIPDG< typename DiscretizationType::AnsatzSpaceType,
                                                              VectorType,
                                                              typename DiscretizationType::ProblemType,
                                                              GridType > Estimator;

public:
  OS2014Spe10Model1Example(const std::string partitioning = "[1 1 1]",
                           const DUNE_STUFF_SSIZE_T num_refinements = 0,
                           const ssize_t info_log_levels  = 0,
                           const ssize_t debug_log_levels = -1,
                           const bool enable_warnings = true,
                           const bool enable_colors   = true,
                           const std::string info_color  = DSC::TimedLogging::default_info_color(),
                           const std::string debug_color = DSC::TimedLogging::default_debug_color(),
                           const std::string warn_color  = DSC::TimedLogging::default_warning_color())
    : internal::Initializer(info_log_levels,
                            debug_log_levels,
                            enable_warnings,
                            enable_colors,
                            info_color,
                            debug_color,
                            warn_color)
    , test_case_({{"mu", Dune::Pymor::Parameter("mu", 1)},     // <- it does not matter which parameters we give to the
                  {"mu_hat", Dune::Pymor::Parameter("mu", 1)}, //    test case here, since we use test_case_.problem()
                  {"mu_bar", Dune::Pymor::Parameter("mu", 1)}, //    (which is the parametric problem) anyway
                  {"mu_minimizing", Dune::Pymor::Parameter("mu", 1)}},
                 partitioning,
                 boost::numeric_cast< size_t >(num_refinements))
    , reference_test_case_({{"mu", Dune::Pymor::Parameter("mu", 1)},
                            {"mu_hat", Dune::Pymor::Parameter("mu", 1)},
                            {"mu_bar", Dune::Pymor::Parameter("mu", 1)},
                            {"mu_minimizing", Dune::Pymor::Parameter("mu", 1)}},
                           partitioning,
                           boost::numeric_cast< size_t >(num_refinements + 1))
    , discretization_(*test_case_./*reference*/level_provider(0),
                      test_case_.boundary_info(),
                      test_case_.problem())
    , reference_discretization_(*reference_test_case_.reference_provider(),
                                reference_test_case_.boundary_info(),
                                reference_test_case_.problem())
  {
    auto logger = DSC::TimedLogger().get("OS2014.spe10model1example");
    logger.info() << "initializing discretization... " << std::flush;
    discretization_.init();
    reference_discretization_.init();
    logger.info() << "done (grid has " << discretization_.grid_view()->indexSet().size(0)
                  << " elements, discretization has " << discretization_.ansatz_space()->mapper().size() << " DoFs)"
                  << std::endl;
  } // ... OS2014Spe10Model1Example(...)

  const TestCaseType& test_case() const
  {
    return test_case_;
  }

  DiscretizationType& discretization()
  {
    return discretization_;
  }

  DiscretizationType* discretization_and_return_ptr() const
  {
    return new DiscretizationType(discretization_);
  }

  VectorType project(const std::string expression) const
  {
    using namespace Dune;
    typedef typename DiscretizationType::AnsatzSpaceType AnsatzSpaceType;
    typedef GDT::DiscreteFunction< AnsatzSpaceType, VectorType > DiscreteFunctionType;
    DiscreteFunctionType discrete_function(*discretization_.ansatz_space());

    typedef Stuff::Functions::Expression< typename DiscreteFunctionType::EntityType,
                                          typename DiscreteFunctionType::DomainFieldType,
                                          DiscreteFunctionType::dimDomain,
                                          typename DiscreteFunctionType::RangeFieldType,
                                          DiscreteFunctionType::dimRange > ExpressionFunctionType;
    ExpressionFunctionType func("x", expression);

    GDT::Operators::Projection< typename DiscretizationType::GridViewType > projection(*discretization_.grid_view());
    projection.apply(func, discrete_function);

    return discrete_function.vector();
  } // ... project(...)

  RangeFieldType compute_error(const VectorType& solution,
                               const std::string product_type = "",
                               const Dune::Pymor::Parameter mu = Dune::Pymor::Parameter(),
                               const Dune::Pymor::Parameter mu_product = Dune::Pymor::Parameter())
  {
    const std::string type = (product_type.empty() && reference_discretization_.available_products().size() == 1)
                             ? reference_discretization_.available_products()[0]
                             : product_type;
    // wrap solution into a discrete function
    using namespace Dune;
    typedef typename DiscretizationType::AnsatzSpaceType AnsatzSpaceType;
    typedef GDT::ConstDiscreteFunction< AnsatzSpaceType, VectorType > ConstDiscreteFunctionType;
    ConstDiscreteFunctionType coarse_solution(*discretization_.ansatz_space(), solution);
    // prolong to reference grid view
    typedef GDT::DiscreteFunction< AnsatzSpaceType, VectorType > DiscreteFunctionType;
    DiscreteFunctionType fine_solution(*reference_discretization_.ansatz_space());
    GDT::Operators::Prolongation< typename DiscretizationType::GridViewType >
        prolongation_operator(*reference_discretization_.grid_view());
    prolongation_operator.apply(coarse_solution, fine_solution);
    // compute reference solution
    DiscreteFunctionType reference_solution(*reference_discretization_.ansatz_space());
    reference_discretization_.solve(reference_solution.vector(), mu);
    // compute error
    const auto product = reference_discretization_.get_product(type).freeze_parameter(mu_product);
    const auto difference = reference_solution.vector() - fine_solution.vector();
    return std::sqrt(product.apply2(difference, difference));
  } // ... compute_error(...)

  RangeFieldType compute_jump_norm(const VectorType& solution_vector,
                                   const Dune::Pymor::Parameter mu_product = Dune::Pymor::Parameter())
  {
    using namespace Dune;
    typedef typename DiscretizationType::AnsatzSpaceType AnsatzSpaceType;
    typedef GDT::ConstDiscreteFunction< AnsatzSpaceType, VectorType > ConstDiscreteFunctionType;
    ConstDiscreteFunctionType solution(*discretization_.ansatz_space(), solution_vector);
    const auto diffusion_factor = discretization_.problem().diffusion_factor()->with_mu(mu_product);
    const auto diffusion_tensor = discretization_.problem().diffusion_tensor()->with_mu(mu_product);
    typedef GDT::Products::EllipticSWIPDGPenaltyLocalizable
        < typename DiscretizationType::GridViewType,
          typename DiscretizationType::ProblemType::DiffusionFactorType::NonparametricType,
          ConstDiscreteFunctionType,
          ConstDiscreteFunctionType,
          RangeFieldType,
          typename DiscretizationType::ProblemType::DiffusionTensorType::NonparametricType > ProductType;
    ProductType penalty_product(*discretization_.grid_view(),
                                solution,
                                solution,
                                *diffusion_factor,
                                *diffusion_tensor,
                                2);
    return std::sqrt(penalty_product.apply2());
  } // ... compute_jump_norm(...)

  std::vector< std::string > available_estimators() const
  {
    return Estimator::available();
  }

  RangeFieldType estimate(const VectorType& vector,
                          const std::string type,
                          const Dune::Pymor::Parameter mu_hat = Dune::Pymor::Parameter(),
                          const Dune::Pymor::Parameter mu_bar = Dune::Pymor::Parameter(),
                          const Dune::Pymor::Parameter mu     = Dune::Pymor::Parameter())
  {
    return Estimator::estimate(*discretization_.ansatz_space(),
                               vector,
                               discretization_.problem(),
                               type,
                               {{"mu_hat",        mu_hat},
                                {"mu_bar",        mu_bar},
                                {"mu",            mu},
                                {"mu_minimizing", Dune::Pymor::Parameter("mu", 0.1)}});
  } // ... estimate(...)

public:
  TestCaseType test_case_;
  TestCaseType reference_test_case_;
  DiscretizationType discretization_;
  DiscretizationType reference_discretization_;
}; // class OS2014Spe10Model1Example

#endif // DUNE_HDD_EXAMPLES_LINEARELLIPTIC_OS2014_HH
<commit_msg>[examples.linearelliptic.OS2014] update grid view usage<commit_after>// This file is part of the dune-hdd project:
//   http://users.dune-project.org/projects/dune-hdd
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_HDD_EXAMPLES_LINEARELLIPTIC_OS2014_HH
#define DUNE_HDD_EXAMPLES_LINEARELLIPTIC_OS2014_HH

#define DUNE_HDD_LINEARELLIPTIC_TESTCASES_BASE_DISABLE_WARNING

#include <boost/numeric/conversion/cast.hpp>

#include <dune/fem/misc/mpimanager.hh>

#include <dune/stuff/common/logging.hh>
#include <dune/stuff/functions/expression.hh>

#include <dune/pymor/parameters/base.hh>

#include <dune/gdt/discretefunction/default.hh>
#include <dune/gdt/operators/projections.hh>
#include <dune/gdt/operators/prolongations.hh>
#include <dune/gdt/playground/products/elliptic-swipdg.hh>

#include <dune/hdd/linearelliptic/testcases/spe10.hh>
#include <dune/hdd/linearelliptic/discretizations/block-swipdg.hh>
#include <dune/hdd/linearelliptic/estimators/block-swipdg.hh>

namespace internal {

class Initializer
{
public:
  Initializer(const ssize_t info_log_levels,
              const ssize_t debug_log_levels,
              const bool enable_warnings,
              const bool enable_colors,
              const std::string info_color,
              const std::string debug_color,
              const std::string warn_color)
  {
    try {
      int argc = 0;
      char** argv = new char* [0];
      Dune::Fem::MPIManager::initialize(argc, argv);
    } catch (...) {}
    DSC::TimedLogger().create(info_log_levels,
                              debug_log_levels,
                              enable_warnings,
                              enable_colors,
                              info_color,
                              debug_color,
                              warn_color);
    DSC::TimedLogger().get("OS2014.spe10model1example").info() << "creating grid and problem... " << std::endl;
  }
}; // class Initializer

} // namespace internal

template< class GridType >
class OS2014Spe10Model1Example
  : internal::Initializer
{
  static_assert(GridType::dimension == 2, "Only available in 2d!");
public:
  typedef Dune::HDD::LinearElliptic::TestCases::Spe10::ParametricBlockModel1< GridType > TestCaseType;
  typedef double RangeFieldType;
  typedef Dune::HDD::LinearElliptic::Discretizations::BlockSWIPDG< GridType, RangeFieldType, 1 > DiscretizationType;
  typedef typename DiscretizationType::VectorType VectorType;

private:
  typedef Dune::HDD::LinearElliptic::Estimators::BlockSWIPDG< typename DiscretizationType::AnsatzSpaceType,
                                                              VectorType,
                                                              typename DiscretizationType::ProblemType,
                                                              GridType > Estimator;

public:
  OS2014Spe10Model1Example(const std::string partitioning = "[1 1 1]",
                           const DUNE_STUFF_SSIZE_T num_refinements = 0,
                           const ssize_t info_log_levels  = 0,
                           const ssize_t debug_log_levels = -1,
                           const bool enable_warnings = true,
                           const bool enable_colors   = true,
                           const std::string info_color  = DSC::TimedLogging::default_info_color(),
                           const std::string debug_color = DSC::TimedLogging::default_debug_color(),
                           const std::string warn_color  = DSC::TimedLogging::default_warning_color())
    : internal::Initializer(info_log_levels,
                            debug_log_levels,
                            enable_warnings,
                            enable_colors,
                            info_color,
                            debug_color,
                            warn_color)
    , test_case_({{"mu", Dune::Pymor::Parameter("mu", 1)},     // <- it does not matter which parameters we give to the
                  {"mu_hat", Dune::Pymor::Parameter("mu", 1)}, //    test case here, since we use test_case_.problem()
                  {"mu_bar", Dune::Pymor::Parameter("mu", 1)}, //    (which is the parametric problem) anyway
                  {"mu_minimizing", Dune::Pymor::Parameter("mu", 1)}},
                 partitioning,
                 boost::numeric_cast< size_t >(num_refinements))
    , reference_test_case_({{"mu", Dune::Pymor::Parameter("mu", 1)},
                            {"mu_hat", Dune::Pymor::Parameter("mu", 1)},
                            {"mu_bar", Dune::Pymor::Parameter("mu", 1)},
                            {"mu_minimizing", Dune::Pymor::Parameter("mu", 1)}},
                           partitioning,
                           boost::numeric_cast< size_t >(num_refinements + 1))
    , discretization_(*test_case_./*reference*/level_provider(0),
                      test_case_.boundary_info(),
                      test_case_.problem())
    , reference_discretization_(*reference_test_case_.reference_provider(),
                                reference_test_case_.boundary_info(),
                                reference_test_case_.problem())
  {
    auto logger = DSC::TimedLogger().get("OS2014.spe10model1example");
    logger.info() << "initializing discretization... " << std::flush;
    discretization_.init();
    reference_discretization_.init();
    logger.info() << "done (grid has " << discretization_.grid_view().indexSet().size(0)
                  << " elements, discretization has " << discretization_.ansatz_space()->mapper().size() << " DoFs)"
                  << std::endl;
  } // ... OS2014Spe10Model1Example(...)

  const TestCaseType& test_case() const
  {
    return test_case_;
  }

  DiscretizationType& discretization()
  {
    return discretization_;
  }

  DiscretizationType* discretization_and_return_ptr() const
  {
    return new DiscretizationType(discretization_);
  }

  VectorType project(const std::string expression) const
  {
    using namespace Dune;
    typedef typename DiscretizationType::AnsatzSpaceType AnsatzSpaceType;
    typedef GDT::DiscreteFunction< AnsatzSpaceType, VectorType > DiscreteFunctionType;
    DiscreteFunctionType discrete_function(*discretization_.ansatz_space());

    typedef Stuff::Functions::Expression< typename DiscreteFunctionType::EntityType,
                                          typename DiscreteFunctionType::DomainFieldType,
                                          DiscreteFunctionType::dimDomain,
                                          typename DiscreteFunctionType::RangeFieldType,
                                          DiscreteFunctionType::dimRange > ExpressionFunctionType;
    ExpressionFunctionType func("x", expression);

    GDT::Operators::Projection< typename DiscretizationType::GridViewType > projection(discretization_.grid_view());
    projection.apply(func, discrete_function);

    return discrete_function.vector();
  } // ... project(...)

  RangeFieldType compute_error(const VectorType& solution,
                               const std::string product_type = "",
                               const Dune::Pymor::Parameter mu = Dune::Pymor::Parameter(),
                               const Dune::Pymor::Parameter mu_product = Dune::Pymor::Parameter())
  {
    const std::string type = (product_type.empty() && reference_discretization_.available_products().size() == 1)
                             ? reference_discretization_.available_products()[0]
                             : product_type;
    // wrap solution into a discrete function
    using namespace Dune;
    typedef typename DiscretizationType::AnsatzSpaceType AnsatzSpaceType;
    typedef GDT::ConstDiscreteFunction< AnsatzSpaceType, VectorType > ConstDiscreteFunctionType;
    ConstDiscreteFunctionType coarse_solution(*discretization_.ansatz_space(), solution);
    // prolong to reference grid view
    typedef GDT::DiscreteFunction< AnsatzSpaceType, VectorType > DiscreteFunctionType;
    DiscreteFunctionType fine_solution(*reference_discretization_.ansatz_space());
    GDT::Operators::Prolongation< typename DiscretizationType::GridViewType >
        prolongation_operator(reference_discretization_.grid_view());
    prolongation_operator.apply(coarse_solution, fine_solution);
    // compute reference solution
    DiscreteFunctionType reference_solution(*reference_discretization_.ansatz_space());
    reference_discretization_.solve(reference_solution.vector(), mu);
    // compute error
    const auto product = reference_discretization_.get_product(type).freeze_parameter(mu_product);
    const auto difference = reference_solution.vector() - fine_solution.vector();
    return std::sqrt(product.apply2(difference, difference));
  } // ... compute_error(...)

  RangeFieldType compute_jump_norm(const VectorType& solution_vector,
                                   const Dune::Pymor::Parameter mu_product = Dune::Pymor::Parameter())
  {
    using namespace Dune;
    typedef typename DiscretizationType::AnsatzSpaceType AnsatzSpaceType;
    typedef GDT::ConstDiscreteFunction< AnsatzSpaceType, VectorType > ConstDiscreteFunctionType;
    ConstDiscreteFunctionType solution(*discretization_.ansatz_space(), solution_vector);
    const auto diffusion_factor = discretization_.problem().diffusion_factor()->with_mu(mu_product);
    const auto diffusion_tensor = discretization_.problem().diffusion_tensor()->with_mu(mu_product);
    typedef GDT::Products::EllipticSWIPDGPenaltyLocalizable
        < typename DiscretizationType::GridViewType,
          typename DiscretizationType::ProblemType::DiffusionFactorType::NonparametricType,
          ConstDiscreteFunctionType,
          ConstDiscreteFunctionType,
          RangeFieldType,
          typename DiscretizationType::ProblemType::DiffusionTensorType::NonparametricType > ProductType;
    ProductType penalty_product(discretization_.grid_view(),
                                solution,
                                solution,
                                *diffusion_factor,
                                *diffusion_tensor,
                                2);
    return std::sqrt(penalty_product.apply2());
  } // ... compute_jump_norm(...)

  std::vector< std::string > available_estimators() const
  {
    return Estimator::available();
  }

  RangeFieldType estimate(const VectorType& vector,
                          const std::string type,
                          const Dune::Pymor::Parameter mu_hat = Dune::Pymor::Parameter(),
                          const Dune::Pymor::Parameter mu_bar = Dune::Pymor::Parameter(),
                          const Dune::Pymor::Parameter mu     = Dune::Pymor::Parameter())
  {
    return Estimator::estimate(*discretization_.ansatz_space(),
                               vector,
                               discretization_.problem(),
                               type,
                               {{"mu_hat",        mu_hat},
                                {"mu_bar",        mu_bar},
                                {"mu",            mu},
                                {"mu_minimizing", Dune::Pymor::Parameter("mu", 0.1)}});
  } // ... estimate(...)

public:
  TestCaseType test_case_;
  TestCaseType reference_test_case_;
  DiscretizationType discretization_;
  DiscretizationType reference_discretization_;
}; // class OS2014Spe10Model1Example

#endif // DUNE_HDD_EXAMPLES_LINEARELLIPTIC_OS2014_HH
<|endoftext|>


<commit_before>/**
 * \file
 * \brief SignalsReceiverControlBlock class header
 *
 * \author Copyright (C) 2015-2017 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#ifndef INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SIGNALSRECEIVERCONTROLBLOCK_HPP_
#define INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SIGNALSRECEIVERCONTROLBLOCK_HPP_

#include "distortos/SignalSet.hpp"

#include <cstdint>

union sigval;

namespace distortos
{

class SignalAction;
class SignalInformation;
class SignalInformationQueueWrapper;
class SignalsCatcher;

namespace internal
{

class SignalInformationQueue;
class SignalsCatcherControlBlock;
class ThreadControlBlock;

/// SignalsReceiverControlBlock class is a structure required by threads for "receiving" of signals
class SignalsReceiverControlBlock
{
public:

	/**
	 * \brief SignalsReceiverControlBlock's constructor
	 *
	 * \param [in] signalInformationQueueWrapper is a pointer to SignalInformationQueueWrapper for this receiver,
	 * nullptr to disable queuing of signals for this receiver
	 * \param [in] signalsCatcher is a pointer to SignalsCatcher for this receiver, nullptr if this receiver cannot
	 * catch/handle signals
	 */

	explicit SignalsReceiverControlBlock(SignalInformationQueueWrapper* signalInformationQueueWrapper,
			SignalsCatcher* signalsCatcher);

	/**
	 * \brief Accepts (clears) one of signals that are pending.
	 *
	 * This should be called when the signal is "accepted".
	 *
	 * \param [in] signalNumber is the signal that will be accepted, [0; 31]
	 *
	 * \return pair with return code (0 on success, error code otherwise) and SignalInformation object for accepted
	 * signal; error codes:
	 * - EAGAIN - no signal specified by \a signalNumber was pending;
	 * - EINVAL - \a signalNumber value is invalid;
	 */

	std::pair<int, SignalInformation> acceptPendingSignal(uint8_t signalNumber);

	/**
	 * \brief Hook function executed when delivery of signals is started.
	 *
	 * Calls SignalsCatcherControlBlock::deliveryOfSignalsStartedHook().
	 *
	 * \attention This function should be called only by the function that delivers signals (deliverSignals()).
	 *
	 * \return 0 on success, error code otherwise:
	 * - ENOTSUP - catching/handling of signals is disabled for this receiver;
	 */

	int deliveryOfSignalsStartedHook() const;

	/**
	 * \brief Generates signal for associated thread.
	 *
	 * Similar to pthread_kill() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_kill.html
	 *
	 * Adds the signalNumber to set of pending signals. If associated thread is currently waiting for this signal, it
	 * will be unblocked.
	 *
	 * \param [in] signalNumber is the signal that will be generated, [0; 31]
	 * \param [in] threadControlBlock is a reference to associated ThreadControlBlock
	 *
	 * \return 0 on success, error code otherwise:
	 * - EINVAL - \a signalNumber value is invalid;
	 * - ENOMEM - amount of free stack is too small to request delivery of signals;
	 */

	int generateSignal(uint8_t signalNumber, ThreadControlBlock& threadControlBlock);

	/**
	 * \return set of currently pending signals
	 */

	SignalSet getPendingSignalSet() const;

	/**
	 * \brief Gets SignalAction associated with given signal number.
	 *
	 * Similar to sigaction() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaction.html
	 *
	 * \param [in] signalNumber is the signal for which the association is requested, [0; 31]
	 *
	 * \return pair with return code (0 on success, error code otherwise) and SignalAction that is associated with
	 * \a signalNumber, default-constructed object if no association was found;
	 * error codes:
	 * - EINVAL - \a signalNumber value is invalid;
	 * - ENOTSUP - catching/handling of signals is disabled for this receiver;
	 */

	std::pair<int, SignalAction> getSignalAction(uint8_t signalNumber) const;

	/**
	 * \brief Gets signal mask for associated thread.
	 *
	 * Similar to pthread_sigmask() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_sigmask.html#
	 *
	 * \return SignalSet with signal mask for associated thread
	 */

	SignalSet getSignalMask() const;

	/**
	 * \brief Queues signal for associated thread.
	 *
	 * Similar to sigqueue() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigqueue.html
	 *
	 * Queues the signalNumber and signal value (sigval union) in associated SignalInformationQueue object. If
	 * associated thread is currently waiting for this signal, it will be unblocked.
	 *
	 * \param [in] signalNumber is the signal that will be queued, [0; 31]
	 * \param [in] value is the signal value
	 * \param [in] threadControlBlock is a reference to associated ThreadControlBlock
	 *
	 * \return 0 on success, error code otherwise:
	 * - EAGAIN - no resources are available to queue the signal, maximal number of signals is already queued in
	 * associated SignalInformationQueue object;
	 * - EINVAL - \a signalNumber value is invalid;
	 * - ENOMEM - amount of free stack is too small to request delivery of signals;
	 * - ENOTSUP - queuing of signals is disabled for this receiver;
	 */

	int queueSignal(uint8_t signalNumber, sigval value, ThreadControlBlock& threadControlBlock) const;

	/**
	 * \brief Sets association for given signal number.
	 *
	 * Similar to sigaction() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaction.html
	 *
	 * \param [in] signalNumber is the signal for which the association will be set, [0; 31]
	 * \param [in] signalAction is a reference to SignalAction that will be associated with given signal number, object
	 * in internal storage is copy-constructed
	 *
	 * \return pair with return code (0 on success, error code otherwise) and SignalAction that was associated with
	 * \a signalNumber, default-constructed object if no association was found;
	 * error codes:
	 * - EAGAIN - no resources are available to associate \a signalNumber with \a signalAction;
	 * - EINVAL - \a signalNumber value is invalid;
	 * - ENOTSUP - catching/handling of signals is disabled for this receiver;
	 */

	std::pair<int, SignalAction> setSignalAction(uint8_t signalNumber, const SignalAction& signalAction);

	/**
	 * \brief Sets signal mask for associated thread.
	 *
	 * Similar to pthread_sigmask() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_sigmask.html#
	 *
	 * \param [in] signalMask is the SignalSet with new signal mask for associated thread
	 * \param [in] requestDelivery selects whether delivery of signals will be requested if any pending signal is
	 * unblocked (true) or not (false)
	 *
	 * \return 0 on success, error code otherwise:
	 * - ENOMEM - amount of free stack is too small to request delivery of signals;
	 * - ENOTSUP - catching/handling of signals is disabled for this receiver;
	 */

	int setSignalMask(SignalSet signalMask, bool requestDelivery);

	/**
	 * \param [in] signalSet is a pointer to set of signals that will be "waited for", nullptr when wait was terminated
	 */

	void setWaitingSignalSet(const SignalSet* const signalSet)
	{
		waitingSignalSet_ = signalSet;
	}

private:

	/**
	 * \brief Checks whether signal is ignored.
	 *
	 * Signal is ignored if it has no SignalAction object associated. Signal is never ignored if catching/handling of
	 * signals is disabled for this receiver.
	 *
	 * \param [in] signalNumber is the signal for which the check will be performed, [0; 31]
	 *
	 * \return pair with return code (0 on success, error code otherwise) and boolean telling whether the signal is
	 * ignored (true) or not (false);
	 * error codes:
	 * - EINVAL - \a signalNumber value is invalid;
	 */

	std::pair<int, bool> isSignalIgnored(uint8_t signalNumber) const;

	/**
	 * \brief Actions executed after signal is "generated" with generateSignal() or queueSignal().
	 *
	 * If associated thread is currently waiting for the signal that was generated, it will be unblocked.
	 *
	 * \param [in] signalNumber is the signal that was generated, [0; 31]
	 * \param [in] threadControlBlock is a reference to associated ThreadControlBlock
	 *
	 * \return 0 on success, error code otherwise:
	 * - EINVAL - \a signalNumber value is invalid;
	 * - ENOMEM - amount of free stack is too small to request delivery of signals;
	 */

	int postGenerate(uint8_t signalNumber, ThreadControlBlock& threadControlBlock) const;

	/// set of pending signals
	SignalSet pendingSignalSet_;

	/// pointer to set of "waited for" signals, nullptr if associated thread is not waiting for any signals
	const SignalSet* waitingSignalSet_;

	/// pointer to SignalsCatcherControlBlock for this receiver, nullptr if this receiver cannot catch/handle signals
	SignalsCatcherControlBlock* signalsCatcherControlBlock_;

	/// pointer to SignalInformationQueue for this receiver, nullptr if this receiver cannot queue signals
	SignalInformationQueue* signalInformationQueue_;
};

}	// namespace internal

}	// namespace distortos

#endif	// INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SIGNALSRECEIVERCONTROLBLOCK_HPP_
<commit_msg>Simplify comments in SignalsReceiverControlBlock.hpp<commit_after>/**
 * \file
 * \brief SignalsReceiverControlBlock class header
 *
 * \author Copyright (C) 2015-2017 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#ifndef INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SIGNALSRECEIVERCONTROLBLOCK_HPP_
#define INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SIGNALSRECEIVERCONTROLBLOCK_HPP_

#include "distortos/SignalSet.hpp"

#include <cstdint>

union sigval;

namespace distortos
{

class SignalAction;
class SignalInformation;
class SignalInformationQueueWrapper;
class SignalsCatcher;

namespace internal
{

class SignalInformationQueue;
class SignalsCatcherControlBlock;
class ThreadControlBlock;

/// SignalsReceiverControlBlock class is a structure required by threads for "receiving" of signals
class SignalsReceiverControlBlock
{
public:

	/**
	 * \brief SignalsReceiverControlBlock's constructor
	 *
	 * \param [in] signalInformationQueueWrapper is a pointer to SignalInformationQueueWrapper for this receiver,
	 * nullptr to disable queuing of signals for this receiver
	 * \param [in] signalsCatcher is a pointer to SignalsCatcher for this receiver, nullptr if this receiver cannot
	 * catch/handle signals
	 */

	explicit SignalsReceiverControlBlock(SignalInformationQueueWrapper* signalInformationQueueWrapper,
			SignalsCatcher* signalsCatcher);

	/**
	 * \brief Accepts (clears) one of signals that are pending.
	 *
	 * This should be called when the signal is "accepted".
	 *
	 * \param [in] signalNumber is the signal that will be accepted, [0; 31]
	 *
	 * \return pair with return code (0 on success, error code otherwise) and SignalInformation object for accepted
	 * signal; error codes:
	 * - EAGAIN - no signal specified by \a signalNumber was pending;
	 * - error codes returned by SignalInformationQueue::acceptQueuedSignal() (except EAGAIN);
	 * - error codes returned by SignalSet::remove();
	 * - error codes returned by SignalSet::test();
	 */

	std::pair<int, SignalInformation> acceptPendingSignal(uint8_t signalNumber);

	/**
	 * \brief Hook function executed when delivery of signals is started.
	 *
	 * Calls SignalsCatcherControlBlock::deliveryOfSignalsStartedHook().
	 *
	 * \attention This function should be called only by the function that delivers signals (deliverSignals()).
	 *
	 * \return 0 on success, error code otherwise:
	 * - ENOTSUP - catching/handling of signals is disabled for this receiver;
	 */

	int deliveryOfSignalsStartedHook() const;

	/**
	 * \brief Generates signal for associated thread.
	 *
	 * Similar to pthread_kill() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_kill.html
	 *
	 * Adds the signalNumber to set of pending signals. If associated thread is currently waiting for this signal, it
	 * will be unblocked.
	 *
	 * \param [in] signalNumber is the signal that will be generated, [0; 31]
	 * \param [in] threadControlBlock is a reference to associated ThreadControlBlock
	 *
	 * \return 0 on success, error code otherwise:
	 * - error codes returned by isSignalIgnored();
	 * - error codes returned by postGenerate();
	 */

	int generateSignal(uint8_t signalNumber, ThreadControlBlock& threadControlBlock);

	/**
	 * \return set of currently pending signals
	 */

	SignalSet getPendingSignalSet() const;

	/**
	 * \brief Gets SignalAction associated with given signal number.
	 *
	 * Similar to sigaction() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaction.html
	 *
	 * \param [in] signalNumber is the signal for which the association is requested, [0; 31]
	 *
	 * \return pair with return code (0 on success, error code otherwise) and SignalAction that is associated with
	 * \a signalNumber, default-constructed object if no association was found; error codes:
	 * - ENOTSUP - catching/handling of signals is disabled for this receiver;
	 * - error codes returned by SignalsCatcherControlBlock::getAssociation();
	 */

	std::pair<int, SignalAction> getSignalAction(uint8_t signalNumber) const;

	/**
	 * \brief Gets signal mask for associated thread.
	 *
	 * Similar to pthread_sigmask() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_sigmask.html#
	 *
	 * \return SignalSet with signal mask for associated thread
	 */

	SignalSet getSignalMask() const;

	/**
	 * \brief Queues signal for associated thread.
	 *
	 * Similar to sigqueue() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigqueue.html
	 *
	 * Queues the signalNumber and signal value (sigval union) in associated SignalInformationQueue object. If
	 * associated thread is currently waiting for this signal, it will be unblocked.
	 *
	 * \param [in] signalNumber is the signal that will be queued, [0; 31]
	 * \param [in] value is the signal value
	 * \param [in] threadControlBlock is a reference to associated ThreadControlBlock
	 *
	 * \return 0 on success, error code otherwise:
	 * - ENOTSUP - queuing of signals is disabled for this receiver;
	 * - error codes returned by isSignalIgnored();
	 * - error codes returned by postGenerate();
	 * - error codes returned by SignalInformationQueue::queueSignal();
	 */

	int queueSignal(uint8_t signalNumber, sigval value, ThreadControlBlock& threadControlBlock) const;

	/**
	 * \brief Sets association for given signal number.
	 *
	 * Similar to sigaction() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaction.html
	 *
	 * \param [in] signalNumber is the signal for which the association will be set, [0; 31]
	 * \param [in] signalAction is a reference to SignalAction that will be associated with given signal number, object
	 * in internal storage is copy-constructed
	 *
	 * \return pair with return code (0 on success, error code otherwise) and SignalAction that was associated with
	 * \a signalNumber, default-constructed object if no association was found; error codes:
	 * - ENOTSUP - catching/handling of signals is disabled for this receiver;
	 * - error codes returned by acceptPendingSignal() (except EAGAIN);
	 * - error codes returned by SignalsCatcherControlBlock::setAssociation();
	 */

	std::pair<int, SignalAction> setSignalAction(uint8_t signalNumber, const SignalAction& signalAction);

	/**
	 * \brief Sets signal mask for associated thread.
	 *
	 * Similar to pthread_sigmask() - http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_sigmask.html#
	 *
	 * \param [in] signalMask is the SignalSet with new signal mask for associated thread
	 * \param [in] requestDelivery selects whether delivery of signals will be requested if any pending signal is
	 * unblocked (true) or not (false)
	 *
	 * \return 0 on success, error code otherwise:
	 * - ENOTSUP - catching/handling of signals is disabled for this receiver;
	 * - error codes returned by SignalsCatcherControlBlock::setSignalMask();
	 */

	int setSignalMask(SignalSet signalMask, bool requestDelivery);

	/**
	 * \param [in] signalSet is a pointer to set of signals that will be "waited for", nullptr when wait was terminated
	 */

	void setWaitingSignalSet(const SignalSet* const signalSet)
	{
		waitingSignalSet_ = signalSet;
	}

private:

	/**
	 * \brief Checks whether signal is ignored.
	 *
	 * Signal is ignored if it has no SignalAction object associated. Signal is never ignored if catching/handling of
	 * signals is disabled for this receiver.
	 *
	 * \param [in] signalNumber is the signal for which the check will be performed, [0; 31]
	 *
	 * \return pair with return code (0 on success, error code otherwise) and boolean telling whether the signal is
	 * ignored (true) or not (false); error codes:
	 * - EINVAL - \a signalNumber value is invalid;
	 */

	std::pair<int, bool> isSignalIgnored(uint8_t signalNumber) const;

	/**
	 * \brief Actions executed after signal is "generated" with generateSignal() or queueSignal().
	 *
	 * If associated thread is currently waiting for the signal that was generated, it will be unblocked.
	 *
	 * \param [in] signalNumber is the signal that was generated, [0; 31]
	 * \param [in] threadControlBlock is a reference to associated ThreadControlBlock
	 *
	 * \return 0 on success, error code otherwise:
	 * - error codes returned by SignalsCatcherControlBlock::postGenerate();
	 */

	int postGenerate(uint8_t signalNumber, ThreadControlBlock& threadControlBlock) const;

	/// set of pending signals
	SignalSet pendingSignalSet_;

	/// pointer to set of "waited for" signals, nullptr if associated thread is not waiting for any signals
	const SignalSet* waitingSignalSet_;

	/// pointer to SignalsCatcherControlBlock for this receiver, nullptr if this receiver cannot catch/handle signals
	SignalsCatcherControlBlock* signalsCatcherControlBlock_;

	/// pointer to SignalInformationQueue for this receiver, nullptr if this receiver cannot queue signals
	SignalInformationQueue* signalInformationQueue_;
};

}	// namespace internal

}	// namespace distortos

#endif	// INCLUDE_DISTORTOS_INTERNAL_SYNCHRONIZATION_SIGNALSRECEIVERCONTROLBLOCK_HPP_
<|endoftext|>


<commit_before>/************************************************
 * libgo sample12
 ************************************************
 * 这是一个协程监听器的例子
 * 使用协程监听器 co_listener 可以监听协程的
 * 创建销毁等事件，也可以进行异常处理
 ************************************************/
#include "coroutine.h"
#include <iostream>

using namespace std;

//协程监听器的调用过程：
//                          (正常运行完成)
//                      ---> onCompleted -->
//                      |                  |
// onCreated --> onStart                   ---> onFinished
//                      |                  |
//                      ---> onException -->
//                     (运行时抛出未捕获的异常)
//
//！！注意协程监听器回调方法均不能抛出异常，如果可能有异常抛出，请在回调方法内自行 try...catch 消化掉

//覆盖 co::co_listener 的虚函数实现回调方法
class CoListenerSample: public co_listener {
public:
    /**
     * 协程被创建时被调用
     * （注意此时并未运行在协程中）
     *
     * @prarm task_id 协程ID
     * @prarm eptr
     */
    virtual void onCreated(uint64_t task_id) noexcept {
        cout << "onCreated task_id=" << task_id << endl;
    }

    /**
     * 协程开始运行
     * （本方法运行在协程中）
     *
     * @prarm task_id 协程ID
     * @prarm eptr
     */
    virtual void onStart(uint64_t task_id) noexcept {
        cout << "onStart task_id=" << task_id << endl;
    }

    /**
     * 协程切入后（包括协程首次运行的时候）调用
     * 协程首次运行会在onStart之前调用。
     * （本方法运行在协程中）
     *
     * @prarm task_id 协程ID
     * @prarm eptr
     */
    virtual void onSwapIn(uint64_t task_id) noexcept {
        cout << "onSwapIn task_id=" << task_id << endl;
    }

    /**
     * 协程切出前调用
     * （本方法运行在协程中）
     *
     * @prarm task_id 协程ID
     * @prarm eptr
     */
    virtual void onSwapOut(uint64_t task_id) noexcept {
        cout << "onSwapOut task_id=" << task_id << endl;
    }

    /**
     * 协程正常运行结束（无异常抛出）
     * （本方法运行在协程中）
     *
     * @prarm task_id 协程ID
     */
    virtual void onCompleted(uint64_t task_id) noexcept {
        cout << "onCompleted task_id=" << task_id << endl;
    }

    /**
     * 协程抛出未被捕获的异常（本方法运行在协程中）
     * @prarm task_id 协程ID
     * @prarm eptr 抛出的异常对象指针，可对本指针赋值以修改异常对象，
     *             异常将使用 CoroutineOptions.exception_handle 中
     *             配置的方式处理；赋值为nullptr则表示忽略此异常
     *             ！！注意：当 exception_handle 配置为 immedaitely_throw 时本事件
     *             ！！与 onFinished() 均失效，异常发生时将直接抛出并中断程序的运行，同时生成coredump
     */
    virtual void onException(uint64_t task_id, std::exception_ptr& eptr) noexcept {
        cout << "onException task_id=" << task_id << "  ";

        try {
            rethrow_exception(eptr);
        } catch (exception& e) {
            cout << "onException  e=" << e.what() << endl;
        } catch (...) {
            cout << "unknow exception." << endl;
        }

        //替换掉异常：
        //eptr = make_exception_ptr(runtime_error("runtime_error task_id=" + to_string(task_id)));

        //包装异常：
        //try {
        //    std::rethrow_exception(eptr);
        //} catch (...) {
        //    try {
        //        std::throw_with_nested(std::runtime_error("wrap exception"));
        //    } catch (...) {
        //        eptr = std::current_exception();
        //    }
        //}

        //如果使用以下赋值，就能忽略异常：
        //eptr = nullptr;
    }

    /**
     * 协程运行完成，if(eptr) 为false说明协程正常结束，为true说明协程抛出了了异常
     *
     * @prarm task_id 协程ID
     * @prarm eptr 抛出的异常对象指针，此处只能读取不允许修改其值
     */
    virtual void onFinished(uint64_t task_id, const std::exception_ptr eptr) noexcept {
        cout << "onFinished task_id=" << task_id << "  ";
        if (eptr) {
            try {
                rethrow_exception(eptr);
            } catch (exception& e) {
                cout << "e=" << e.what() << endl;
            } catch (...) {
                cout << "unknow exception." << endl;
            }
        } else {
            cout << " completed." << endl;
        }
    }

};

int main(int argc, char** argv) {
    CoListenerSample listener;

    //设置协程监听器，如果设置为NULL则为取消监听
    set_co_listener(&listener);

    //将异常的处理方式置为输出日志
    co_sched.GetOptions().debug |= co::dbg_exception;
    co_sched.GetOptions().exception_handle = co::eCoExHandle::debugger_only;

    go[] {
        cout << "i am task=" << co_sched.GetCurrentTaskID() << endl;
        cout << "task " << co_sched.GetCurrentTaskID() << " going to sleep for a while" << endl;
        co_sleep(1);
        cout << "task " << co_sched.GetCurrentTaskID() << " returns" << endl;
    };

    go[] {
        cout << "i am task=" << co_sched.GetCurrentTaskID() << endl;
        cout << "task " << co_sched.GetCurrentTaskID() << " going to sleep for a while" << endl;
        co_sleep(1);
        throw logic_error("wtf!!??");
        cout << "task " << co_sched.GetCurrentTaskID() << " returns" << endl;
    };

    co_sched.RunUntilNoTask();
    return 0;
}

<commit_msg>sample12_listener.cpp: comment change<commit_after>/************************************************
 * libgo sample12
 ************************************************
 * 这是一个协程监听器的例子
 * 使用协程监听器 co_listener 可以监听协程的
 * 创建销毁等事件，也可以进行异常处理
 ************************************************/
#include "coroutine.h"
#include <iostream>

using namespace std;

//协程监听器的调用过程：
// s: Scheduler，表示该方法运行在调度器上下文中
// c: Coroutine，表示该方法运行在协程上下文中
//                                             (正常运行完成)
//                                           -->[c]onCompleted->
//                                          |                   |
// [s]onCreated-->[s]onSwapIn-->[c]onStart->*--->[c]onSwapOut-- -->[c]onFinished-->[c]onSwapOut
//                                          |\                | |
//                                          | \<-[s]onSwapIn--V |
//                                          |                   |
//                                           -->[c]onException->
//
//！！注意协程监听器回调方法均不能抛出异常，如果可能有异常抛出，请在回调方法内自行 try...catch 消化掉

//覆盖 co::co_listener 的虚函数实现回调方法
class CoListenerSample: public co_listener {
public:
    /**
     * 协程被创建时被调用
     * （注意此时并未运行在协程中）
     *
     * @prarm task_id 协程ID
     * @prarm eptr
     */
    virtual void onCreated(uint64_t task_id) noexcept {
        cout << "onCreated task_id=" << task_id << endl;
    }

    /**
     * 每次协程切入前调用
     * （注意此时并未运行在协程中）
     *
     * @prarm task_id 协程ID
     * @prarm eptr
     */
    virtual void onSwapIn(uint64_t task_id) noexcept {
        cout << "onSwapIn task_id=" << task_id << endl;
    }

    /**
     * 协程开始运行
     * （本方法运行在协程中）
     *
     * @prarm task_id 协程ID
     * @prarm eptr
     */
    virtual void onStart(uint64_t task_id) noexcept {
        cout << "onStart task_id=" << task_id << endl;
    }

    /**
     * 每次协程切出前调用
     * （本方法运行在协程中）
     *
     * @prarm task_id 协程ID
     * @prarm eptr
     */
    virtual void onSwapOut(uint64_t task_id) noexcept {
        cout << "onSwapOut task_id=" << task_id << endl;
    }

    /**
     * 协程正常运行结束（无异常抛出）
     * （本方法运行在协程中）
     *
     * @prarm task_id 协程ID
     */
    virtual void onCompleted(uint64_t task_id) noexcept {
        cout << "onCompleted task_id=" << task_id << endl;
    }

    /**
     * 协程抛出未被捕获的异常（本方法运行在协程中）
     * @prarm task_id 协程ID
     * @prarm eptr 抛出的异常对象指针，可对本指针赋值以修改异常对象，
     *             异常将使用 CoroutineOptions.exception_handle 中
     *             配置的方式处理；赋值为nullptr则表示忽略此异常
     *             ！！注意：当 exception_handle 配置为 immedaitely_throw 时本事件
     *             ！！与 onFinished() 均失效，异常发生时将直接抛出并中断程序的运行，同时生成coredump
     */
    virtual void onException(uint64_t task_id, std::exception_ptr& eptr) noexcept {
        cout << "onException task_id=" << task_id << "  ";

        try {
            rethrow_exception(eptr);
        } catch (exception& e) {
            cout << "onException  e=" << e.what() << endl;
        } catch (...) {
            cout << "unknow exception." << endl;
        }

        //替换掉异常：
        //eptr = make_exception_ptr(runtime_error("runtime_error task_id=" + to_string(task_id)));

        //包装异常：
        //try {
        //    std::rethrow_exception(eptr);
        //} catch (...) {
        //    try {
        //        std::throw_with_nested(std::runtime_error("wrap exception"));
        //    } catch (...) {
        //        eptr = std::current_exception();
        //    }
        //}

        //如果使用以下赋值，就能忽略异常：
        //eptr = nullptr;
    }

    /**
     * 协程运行完成，if(eptr) 为false说明协程正常结束，为true说明协程抛出了了异常
     *
     * @prarm task_id 协程ID
     * @prarm eptr 抛出的异常对象指针，此处只能读取不允许修改其值
     */
    virtual void onFinished(uint64_t task_id, const std::exception_ptr eptr) noexcept {
        cout << "onFinished task_id=" << task_id << "  ";
        if (eptr) {
            try {
                rethrow_exception(eptr);
            } catch (exception& e) {
                cout << "e=" << e.what() << endl;
            } catch (...) {
                cout << "unknow exception." << endl;
            }
        } else {
            cout << " completed." << endl;
        }
    }

};

int main(int argc, char** argv) {
    CoListenerSample listener;

    //设置协程监听器，如果设置为NULL则为取消监听
    set_co_listener(&listener);

    //将异常的处理方式置为输出日志
    co_sched.GetOptions().debug |= co::dbg_exception;
    co_sched.GetOptions().exception_handle = co::eCoExHandle::debugger_only;

    go[] {
        cout << "i am task=" << co_sched.GetCurrentTaskID() << endl;
        cout << "task " << co_sched.GetCurrentTaskID() << " going to sleep for a while" << endl;
        co_sleep(1);
        cout << "task " << co_sched.GetCurrentTaskID() << " returns" << endl;
    };

    go[] {
        cout << "i am task=" << co_sched.GetCurrentTaskID() << endl;
        cout << "task " << co_sched.GetCurrentTaskID() << " going to sleep for a while" << endl;
        co_sleep(1);
        throw logic_error("wtf!!??");
        cout << "task " << co_sched.GetCurrentTaskID() << " returns" << endl;
    };

    co_sched.RunUntilNoTask();
    return 0;
}

<|endoftext|>