<commit_before>/*
  editinteractor.cpp - Interface for edit interactors
  Copyright (C) 2007 Klarälvdalens Datakonsult AB

  This file is part of GPGME++.

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

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

  You should have received a copy of the GNU Library General Public License
  along with GPGME++; see the file COPYING.LIB.  If not, write to the
  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  Boston, MA 02110-1301, USA.
*/

#include "editinteractor.h"
#include "callbacks.h"
#include "error.h"

#include <gpg-error.h>

#ifdef _WIN32
# include <io.h>
#include <windows.h>
#else
# include <unistd.h>
#endif

#include <cstring>

using namespace GpgME;

class EditInteractor::Private {
    friend class ::GpgME::EditInteractor;
    friend class ::GpgME::CallbackHelper;
    EditInteractor * const q;
public:
    explicit Private( EditInteractor * qq );
    ~Private();

private:
    unsigned int state;
    Error error;
    std::FILE * debug;
};

class GpgME::CallbackHelper {
private:
    static int writeAll( int fd, const void * buf, uint count ) {
        uint toWrite = count;
        while ( toWrite > 0 ) {
#ifdef Q_OS_WIN
            DWORD n;
            if ( !WriteFile( (HANDLE)fd, buf, toWrite, &n, NULL ) )
                return -1;
#else
            const int n = write( fd, buf, toWrite );
#endif
            if ( n < 0 )
                return n;
            toWrite -= n;
        }
        return count;
    }

public:
    static int edit_interactor_callback_impl( void * opaque, gpgme_status_code_t status, const char * args, int fd ) {
        EditInteractor::Private * ei = (EditInteractor::Private*)opaque;

        Error err;

            // advance to next state based on input:
            const unsigned int oldState = ei->state;
            ei->state = ei->q->nextState( status, args, err );
            if ( err ) {
                ei->state = oldState;
                goto error;
            }
            if ( ei->debug )
                std::fprintf( ei->debug, "EditInteractor: %u -> nextState( %u, %s ) -> %u\n",
                              oldState, (unsigned int)status, args ? args : "<null>", ei->state );

            if ( ei->state != oldState &&
                 // if there was an error from before, we stop here (### this looks weird, can this happen at all?)
                 gpg_err_code( ei->error.code() ) == GPG_ERR_NO_ERROR ) {

                // successful state change -> call action
                if ( const char * const result = ei->q->action( err ) ) {
                    if ( err )
                        goto error;
                    if ( ei->debug )
                        std::fprintf( ei->debug, "EditInteractor: action result \"%s\"\n", result );
                    // if there's a result, write it:
                    if ( *result )
                        writeAll( fd, result, std::strlen( result ) );
                    writeAll( fd, "\n", 1 );
                } else {
                    if ( err )
                        goto error;
                    if ( ei->debug )
                        std::fprintf( ei->debug, "EditInteractor: no action result\n" );
                }
            } else {
                if ( ei->debug )
                    std::fprintf( ei->debug, "EditInteractor: no action executed\n" );
            }

    error:
        if ( err ) {
            ei->error = err;
            ei->state = EditInteractor::ErrorState;
        }

        if ( ei->debug )
            std::fprintf( ei->debug, "EditInteractor: error now %u (%s)\n",
                          ei->error.encodedError(), gpg_strerror( ei->error.encodedError() ) );

        return ei->error.encodedError();
    }
};

static gpgme_error_t edit_interactor_callback( void * opaque, gpgme_status_code_t status, const char * args, int fd )
{
    return CallbackHelper::edit_interactor_callback_impl( opaque, status, args, fd );
}

gpgme_edit_cb_t GpgME::edit_interactor_callback = ::edit_interactor_callback;

EditInteractor::Private::Private( EditInteractor * qq )
    : q( qq ),
      state( StartState ),
      error(),
      debug(0)
{

}

EditInteractor::Private::~Private() {}

EditInteractor::EditInteractor()
    : d( new Private( this ) )
{

}

EditInteractor::~EditInteractor() {
    delete d; d = 0;
}

unsigned int EditInteractor::state() const {
    return d->state;
}

Error EditInteractor::lastError() const {
    return d->error;
}

bool EditInteractor::needsNoResponse( unsigned int status ) const {
    switch ( status ) {
    case GPGME_STATUS_EOF:
    case GPGME_STATUS_GOT_IT:
    case GPGME_STATUS_NEED_PASSPHRASE:
    case GPGME_STATUS_NEED_PASSPHRASE_SYM:
    case GPGME_STATUS_GOOD_PASSPHRASE:
    case GPGME_STATUS_BAD_PASSPHRASE:
    case GPGME_STATUS_USERID_HINT:
    case GPGME_STATUS_SIGEXPIRED:
    case GPGME_STATUS_KEYEXPIRED:
        return true;
    default:
        return false;
    }
}

void EditInteractor::setDebugChannel( std::FILE * debug ) {
    d->debug = debug;
}
<commit_msg>Backport r851235 by tmcguire from trunk to the 4.1 branch:<commit_after>/*
  editinteractor.cpp - Interface for edit interactors
  Copyright (C) 2007 Klarälvdalens Datakonsult AB

  This file is part of GPGME++.

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

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

  You should have received a copy of the GNU Library General Public License
  along with GPGME++; see the file COPYING.LIB.  If not, write to the
  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  Boston, MA 02110-1301, USA.
*/

#include "editinteractor.h"
#include "callbacks.h"
#include "error.h"

#include <gpg-error.h>

#ifdef _WIN32
# include <io.h>
#include <windows.h>
#else
# include <unistd.h>
#endif

#include <cerrno>
#include <cstring>

using namespace GpgME;

class EditInteractor::Private {
    friend class ::GpgME::EditInteractor;
    friend class ::GpgME::CallbackHelper;
    EditInteractor * const q;
public:
    explicit Private( EditInteractor * qq );
    ~Private();

private:
    unsigned int state;
    Error error;
    std::FILE * debug;
};

class GpgME::CallbackHelper {
private:
    static int writeAll( int fd, const void * buf, uint count ) {
        uint toWrite = count;
        while ( toWrite > 0 ) {
#ifdef Q_OS_WIN
            DWORD n;
            if ( !WriteFile( (HANDLE)fd, buf, toWrite, &n, NULL ) )
                return -1;
#else
            const int n = write( fd, buf, toWrite );
#endif
            if ( n < 0 )
                return n;
            toWrite -= n;
        }
        return count;
    }

public:
    static int edit_interactor_callback_impl( void * opaque, gpgme_status_code_t status, const char * args, int fd ) {
        EditInteractor::Private * ei = (EditInteractor::Private*)opaque;

        Error err;

            // advance to next state based on input:
            const unsigned int oldState = ei->state;
            ei->state = ei->q->nextState( status, args, err );
            if ( err ) {
                ei->state = oldState;
                goto error;
            }
            if ( ei->debug )
                std::fprintf( ei->debug, "EditInteractor: %u -> nextState( %u, %s ) -> %u\n",
                              oldState, (unsigned int)status, args ? args : "<null>", ei->state );

            if ( ei->state != oldState &&
                 // if there was an error from before, we stop here (### this looks weird, can this happen at all?)
                 gpg_err_code( ei->error.code() ) == GPG_ERR_NO_ERROR ) {

                // successful state change -> call action
                if ( const char * const result = ei->q->action( err ) ) {
                    if ( err )
                        goto error;
                    if ( ei->debug )
                        std::fprintf( ei->debug, "EditInteractor: action result \"%s\"\n", result );
                    // if there's a result, write it:
                    if ( *result ) {
                        errno = 0;
                        if ( writeAll( fd, result, std::strlen( result ) != std::strlen( result ) ) ) {
                            if ( ei->debug )
                                std::fprintf( ei->debug, "EditInteractor: Could not write to fd %d (%s)\n", fd, strerror( errno ) );
                            err = Error( GPG_ERR_GENERAL );
                            goto error;
                        }
                    }
                    errno = 0;
                    if ( writeAll( fd, "\n", 1 ) != 1 ) {
                        if ( ei->debug )
                            std::fprintf( ei->debug, "EditInteractor: Could not write to fd %d (%s)\n", fd, strerror( errno ) );
                        err = Error( GPG_ERR_GENERAL );
                        goto error;
                    }
                } else {
                    if ( err )
                        goto error;
                    if ( ei->debug )
                        std::fprintf( ei->debug, "EditInteractor: no action result\n" );
                }
            } else {
                if ( ei->debug )
                    std::fprintf( ei->debug, "EditInteractor: no action executed\n" );
            }

    error:
        if ( err ) {
            ei->error = err;
            ei->state = EditInteractor::ErrorState;
        }

        if ( ei->debug )
            std::fprintf( ei->debug, "EditInteractor: error now %u (%s)\n",
                          ei->error.encodedError(), gpg_strerror( ei->error.encodedError() ) );

        return ei->error.encodedError();
    }
};

static gpgme_error_t edit_interactor_callback( void * opaque, gpgme_status_code_t status, const char * args, int fd )
{
    return CallbackHelper::edit_interactor_callback_impl( opaque, status, args, fd );
}

gpgme_edit_cb_t GpgME::edit_interactor_callback = ::edit_interactor_callback;

EditInteractor::Private::Private( EditInteractor * qq )
    : q( qq ),
      state( StartState ),
      error(),
      debug(0)
{

}

EditInteractor::Private::~Private() {}

EditInteractor::EditInteractor()
    : d( new Private( this ) )
{

}

EditInteractor::~EditInteractor() {
    delete d; d = 0;
}

unsigned int EditInteractor::state() const {
    return d->state;
}

Error EditInteractor::lastError() const {
    return d->error;
}

bool EditInteractor::needsNoResponse( unsigned int status ) const {
    switch ( status ) {
    case GPGME_STATUS_EOF:
    case GPGME_STATUS_GOT_IT:
    case GPGME_STATUS_NEED_PASSPHRASE:
    case GPGME_STATUS_NEED_PASSPHRASE_SYM:
    case GPGME_STATUS_GOOD_PASSPHRASE:
    case GPGME_STATUS_BAD_PASSPHRASE:
    case GPGME_STATUS_USERID_HINT:
    case GPGME_STATUS_SIGEXPIRED:
    case GPGME_STATUS_KEYEXPIRED:
        return true;
    default:
        return false;
    }
}

void EditInteractor::setDebugChannel( std::FILE * debug ) {
    d->debug = debug;
}
<|endoftext|>


<commit_before>/*
    Copyright 2012 Joe Hermaszewski. All rights reserved.

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice,
    this list of conditions and the following disclaimer.

    2. Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.

    THIS SOFTWARE IS PROVIDED BY JOE HERMASZEWSKI "AS IS" AND ANY EXPRESS OR
    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
    EVENT SHALL JOE HERMASZEWSKI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

    The views and conclusions contained in the software and documentation are
    those of the authors and should not be interpreted as representing official
    policies, either expressed or implied, of Joe Hermaszewski.
*/

#include "type_properties.hpp"

#include <map>
#include <string>
#include <vector>

#include <llvm/Type.h>
#include <llvm/DerivedTypes.h>

#include <engine/types.hpp>

namespace JoeLang
{

Type GetCommonType( Type t1, Type t2 )
{
    const static std::vector<Type> promotion_ordering =
    {
        Type::UNKNOWN_TYPE,
        Type::DOUBLE,
        Type::FLOAT,
        Type::U64,
        Type::I64,
        Type::U32,
        Type::I32,
        Type::U16,
        Type::I16,
        Type::U8,
        Type::I8,
        Type::BOOL
    };

    for( Type t : promotion_ordering )
        if( t1 == t || t2 == t )
            return t;

    //TODO issue warning somewhere around here?
    return Type::UNKNOWN_TYPE;
}

bool IsIntegral( Type t )
{
    return t == Type::BOOL ||
           t == Type::I8   ||
           t == Type::I16  ||
           t == Type::I32  ||
           t == Type::I64  ||
           t == Type::U8   ||
           t == Type::U16  ||
           t == Type::U32  ||
           t == Type::U64;
}

bool IsFloatingPoint( Type t )
{
    return t == Type::DOUBLE ||
           t == Type::FLOAT;
}

bool IsSigned( Type t )
{
    return t == Type::I64 ||
           t == Type::I32 ||
           t == Type::I16 ||
           t == Type::I8;
}

std::size_t SizeOf( Type t )
{
    if( t == Type::DOUBLE ||
        t == Type::U64 ||
        t == Type::I64 )
        return 8;

    if( t == Type::FLOAT ||
        t == Type::U32 ||
        t == Type::I32 )
        return 4;

    if( t == Type::U16 ||
        t == Type::I16 )
        return 2;

    if( t == Type::U8 ||
        t == Type::I8 ||
        t == Type::BOOL )
        return 1;

    return 0;
}

llvm::Type* GetLLVMType( Type t, llvm::LLVMContext& c )
{
    if( t == Type::DOUBLE )
        return llvm::Type::getDoubleTy( c );
    if( t == Type::FLOAT )
        return llvm::Type::getFloatTy( c );
    if( t == Type::BOOL )
        return llvm::Type::getInt1Ty( c );
    if( IsIntegral( t ) )
        return llvm::Type::getIntNTy( c, SizeOf(t)*8 );
    return nullptr;
}

const std::string& GetTypeString( Type t )
{
    const static std::map<Type, std::string> string_map =
    {
        { Type::UNKNOWN_TYPE, "unknown type" },
        { Type::DOUBLE,       "double" },
        { Type::FLOAT,        "float" },
        { Type::U64,          "u64" },
        { Type::I64,          "i64" },
        { Type::U32,          "u32" },
        { Type::I32,          "i32" },
        { Type::U16,          "u16" },
        { Type::I16,          "i16" },
        { Type::U8,           "u8" },
        { Type::I8,           "i8" },
        { Type::BOOL,         "bool" },
        { Type::STRING,       "string" },
    };

    return string_map.at(t);
}

} // namespace JoeLang
<commit_msg>[+] handling STRING in GetCommonType<commit_after>/*
    Copyright 2012 Joe Hermaszewski. All rights reserved.

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice,
    this list of conditions and the following disclaimer.

    2. Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.

    THIS SOFTWARE IS PROVIDED BY JOE HERMASZEWSKI "AS IS" AND ANY EXPRESS OR
    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
    EVENT SHALL JOE HERMASZEWSKI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

    The views and conclusions contained in the software and documentation are
    those of the authors and should not be interpreted as representing official
    policies, either expressed or implied, of Joe Hermaszewski.
*/

#include "type_properties.hpp"

#include <map>
#include <string>
#include <vector>

#include <llvm/Type.h>
#include <llvm/DerivedTypes.h>

#include <engine/types.hpp>

namespace JoeLang
{

Type GetCommonType( Type t1, Type t2 )
{
    const static std::vector<Type> promotion_ordering =
    {
        Type::UNKNOWN_TYPE,
        Type::DOUBLE,
        Type::FLOAT,
        Type::U64,
        Type::I64,
        Type::U32,
        Type::I32,
        Type::U16,
        Type::I16,
        Type::U8,
        Type::I8,
        Type::BOOL
    };

    if( t1 == Type::STRING )
    {
        if( t2 == Type::STRING )
            return Type::STRING;
        else
            return Type::UNKNOWN_TYPE;
    }

    for( Type t : promotion_ordering )
        if( t1 == t || t2 == t )
            return t;

    //TODO issue warning somewhere around here?
    return Type::UNKNOWN_TYPE;
}

bool IsIntegral( Type t )
{
    return t == Type::BOOL ||
           t == Type::I8   ||
           t == Type::I16  ||
           t == Type::I32  ||
           t == Type::I64  ||
           t == Type::U8   ||
           t == Type::U16  ||
           t == Type::U32  ||
           t == Type::U64;
}

bool IsFloatingPoint( Type t )
{
    return t == Type::DOUBLE ||
           t == Type::FLOAT;
}

bool IsSigned( Type t )
{
    return t == Type::I64 ||
           t == Type::I32 ||
           t == Type::I16 ||
           t == Type::I8;
}

std::size_t SizeOf( Type t )
{
    if( t == Type::DOUBLE ||
        t == Type::U64 ||
        t == Type::I64 )
        return 8;

    if( t == Type::FLOAT ||
        t == Type::U32 ||
        t == Type::I32 )
        return 4;

    if( t == Type::U16 ||
        t == Type::I16 )
        return 2;

    if( t == Type::U8 ||
        t == Type::I8 ||
        t == Type::BOOL )
        return 1;

    return 0;
}

llvm::Type* GetLLVMType( Type t, llvm::LLVMContext& c )
{
    if( t == Type::DOUBLE )
        return llvm::Type::getDoubleTy( c );
    if( t == Type::FLOAT )
        return llvm::Type::getFloatTy( c );
    if( t == Type::BOOL )
        return llvm::Type::getInt1Ty( c );
    if( IsIntegral( t ) )
        return llvm::Type::getIntNTy( c, SizeOf(t)*8 );
    return nullptr;
}

const std::string& GetTypeString( Type t )
{
    const static std::map<Type, std::string> string_map =
    {
        { Type::UNKNOWN_TYPE, "unknown type" },
        { Type::DOUBLE,       "double" },
        { Type::FLOAT,        "float" },
        { Type::U64,          "u64" },
        { Type::I64,          "i64" },
        { Type::U32,          "u32" },
        { Type::I32,          "i32" },
        { Type::U16,          "u16" },
        { Type::I16,          "i16" },
        { Type::U8,           "u8" },
        { Type::I8,           "i8" },
        { Type::BOOL,         "bool" },
        { Type::STRING,       "string" },
    };

    return string_map.at(t);
}

} // namespace JoeLang
<|endoftext|>


<commit_before>/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#include "paddle/fluid/operators/concat_op.h"
#include "paddle/fluid/platform/mkldnn_helper.h"

namespace paddle {
namespace operators {

using framework::DataLayout;
using framework::Tensor;
using mkldnn::memory;
using mkldnn::primitive;
using mkldnn::concat;
using mkldnn::stream;
using platform::to_void_cast;

// Generate keys for storing/retriving primitives for this operator
// TODO(jczaja): Make hashing function more optimial
static std::string gethash(const memory::dims& input_dims,
                           const std::string& pooling_type,
                           const std::vector<int>& ksize,
                           const std::vector<int>& strides,
                           const std::vector<int>& paddings,
                           const std::string& suffix) {
  auto dims2str = [](const memory::dims& operand_dims) {
    std::string dstr = "";
    for (size_t i = 0; i < operand_dims.size(); ++i) {
      dstr += std::to_string(operand_dims[i]) + "-";
    }
    return dstr;
  };
  return dims2str(input_dims) + dims2str(ksize) + dims2str(strides) +
         dims2str(paddings) + pooling_type + suffix;
}

static void EnforceLayouts(const std::vector<const Tensor*> inputs) {
  for (auto* input : inputs) {
    const bool is_layout_correct = input->layout() == DataLayout::kMKLDNN;
    const bool is_format_defined = input->format() !=
                                   memory::format::format_undef;
    PADDLE_ENFORCE(is_layout_correct && is_format_defined,
                   "Wrong layout/format set for Input tensor");
  }
}

static memory::primitive_desc CreateMemPrimDesc(
    const framework::Tensor& input, const mkldnn::engine& engine) {
  constexpr auto data_type = mkldnn::memory::f32;
  const auto dims = paddle::framework::vectorize2int(input.dims());
  const auto format = input.format();
  auto description = memory::desc(dims, data_type, format);
  auto mem_prim_desc = memory::primitive_desc(description, engine);
  return mem_prim_desc;
}

static platform::CPUPlace GetCpuPlace(
    const paddle::framework::ExecutionContext& ctx) {
  auto place = ctx.GetPlace();
  PADDLE_ENFORCE(paddle::platform::is_cpu_place(place),
                 "It must use CPUPlace.");
  return boost::get<platform::CPUPlace>(place);
}

template <typename T>
class ConcatMKLDNNOpKernel : public paddle::framework::OpKernel<T> {
 public:
  void Compute(const paddle::framework::ExecutionContext& ctx) const override {
    auto place = GetCpuPlace(ctx);
    auto& dev_ctx =
        ctx.template device_context<platform::MKLDNNDeviceContext>();
    const auto& mkldnn_engine = dev_ctx.GetEngine();

    auto multi_input = ctx.MultiInput<framework::Tensor>("X");
    framework::Tensor* output = ctx.Output<framework::Tensor>("Out");
    int64_t concat_axis = static_cast<int64_t>(ctx.Attr<int>("axis"));

    EnforceLayouts(multi_input);

    std::vector<memory::primitive_desc> srcs_pd;
    std::vector<memory> srcs;
    for (size_t i = 0; i < multi_input.size(); i++) {
        auto mem_prim_desc = CreateMemPrimDesc(*multi_input[i], mkldnn_engine);
        srcs_pd.push_back(mem_prim_desc);
        srcs.push_back(memory(mem_prim_desc, to_void_cast(multi_input[i]->data<T>())));
    }
    auto dst_dims = paddle::framework::vectorize2int(output->dims());
    auto dst_desc = memory::desc(dst_dims, mkldnn::memory::f32, memory::format::any);
    auto concat_pd = concat::primitive_desc(dst_desc, static_cast<int>(concat_axis), srcs_pd);
    auto dst_mem = memory(concat_pd.dst_primitive_desc(), output->mutable_data<T>(place));

    std::vector<primitive::at> inputs; //= {srcs};
    inputs.reserve(srcs.size());
    for (size_t i = 0; i < srcs.size(); i++) {
      inputs.push_back(srcs[i]);
    }
    auto concat_prim = concat(concat_pd, inputs, dst_mem);

    std::vector<primitive> pipeline;
    pipeline.push_back(concat_prim);
    stream(stream::kind::eager).submit(pipeline).wait(); // TODO(mgallus): When this is not workin' split into decl and def

    /*
    const T* input_data = input->data<T>();
    T* output_data = output->mutable_data<T>(ctx.GetPlace());

    std::vector<int> src_tz = paddle::framework::vectorize2int(input->dims());
    std::vector<int> dst_tz = paddle::framework::vectorize2int(output->dims());

    auto input_format = input->format();
    memory::format output_format{memory::format::format_undef};

    const std::string key = gethash(src_tz, pooling_type, ksize, strides,
                                    paddings, ctx.op().Output("Out"));
    const std::string key_pool_p = key + "@pool_p";
    const std::string key_pool_pd = key + "@pool_pd";
    const std::string key_pool_src_mem_p = key + "@pool_src_mem_p";
    const std::string key_pool_dst_mem_p = key + "@pool_dst_mem_p";
    const std::string key_pool_workspace_memory =
        key + "@pool_workspace_memory";

    auto pool_p =
        std::static_pointer_cast<pooling_forward>(dev_ctx.GetBlob(key_pool_p));
    if (pool_p == nullptr) {
      const std::vector<int>& padding_left_top(paddings);
      std::vector<int> padding_right_bottom(paddings);
      bool ceil_mode = ctx.Attr<bool>("ceil_mode");
      if (ceil_mode) {
        CorrectOutputSize(src_tz, dst_tz, ksize, paddings, strides,
                          padding_right_bottom);
      }
      auto src_md = platform::MKLDNNMemDesc(
          src_tz, platform::MKLDNNGetDataType<T>(), input_format);

      auto dst_md = platform::MKLDNNMemDesc(dst_tz, mkldnn::memory::f32,
                                            mkldnn::memory::format::any);

      std::shared_ptr<mkldnn::pooling_forward::primitive_desc> pool_pd =
          CreatePrimitiveDesc(src_md, dst_md, strides, padding_left_top,
                              padding_right_bottom, ksize, pooling_type,
                              mkldnn_engine, ceil_mode, is_test);

      // save pool_pd into global device context to be referred in backward path
      if (!is_test) dev_ctx.SetBlob(key_pool_pd, pool_pd);

      auto src_memory = std::make_shared<memory>(pool_pd->src_primitive_desc(),
                                                 to_void_cast<T>(input_data));
      auto dst_memory =
          std::make_shared<memory>(pool_pd->dst_primitive_desc(), output_data);

      dev_ctx.SetBlob(key_pool_src_mem_p, src_memory);
      dev_ctx.SetBlob(key_pool_dst_mem_p, dst_memory);

      if (is_test) {
        pool_p = std::make_shared<pooling_forward>(*pool_pd, *src_memory,
                                                   *dst_memory);
      } else {
        std::shared_ptr<mkldnn::memory> workspace_memory =
            CreateWorkspaceMemory(pool_pd, pooling_type, mkldnn_engine);

        // save pool_workspace_memory to be referred in backward path
        dev_ctx.SetBlob(key_pool_workspace_memory, workspace_memory);

        pool_p = std::make_shared<pooling_forward>(
            *pool_pd, *src_memory, *dst_memory, *workspace_memory);
      }

      dev_ctx.SetBlob(key_pool_p, pool_p);

      output_format =
          (memory::format)dst_memory->get_primitive_desc().desc().data.format;
    } else {
      // Primitives already exist
      auto pool_src_memory_p =
          std::static_pointer_cast<memory>(dev_ctx.GetBlob(key_pool_src_mem_p));
      PADDLE_ENFORCE(pool_src_memory_p != nullptr,
                     "Fail to find pooling src mem_p in device context");
      auto pool_dst_memory_p =
          std::static_pointer_cast<memory>(dev_ctx.GetBlob(key_pool_dst_mem_p));
      PADDLE_ENFORCE(pool_dst_memory_p != nullptr,
                     "Fail to find pooling dst mem_p in device context");
      pool_src_memory_p->set_data_handle(to_void_cast<T>(input_data));
      pool_dst_memory_p->set_data_handle(output_data);

      output_format = (memory::format)pool_dst_memory_p->get_primitive_desc()
                          .desc()
                          .data.format;
    }

    // push primitive to stream and wait until it's executed
    std::vector<mkldnn::primitive> pipeline{*(pool_p.get())};
    stream(stream::kind::eager).submit(pipeline).wait();
    */
    output->mutable_data(place);
    output->set_layout(DataLayout::kMKLDNN);
    output->set_format((memory::format)dst_mem.get_primitive_desc().desc()
                                              .data.format);
  }
};
}  // namespace operators
}  // namespace paddle

namespace ops = paddle::operators;

REGISTER_OP_KERNEL(concat, MKLDNN, ::paddle::platform::CPUPlace,
                   ops::ConcatMKLDNNOpKernel<float>)
<commit_msg>Refactor MKL-DNN Concat<commit_after>/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#include <memory>
#include "paddle/fluid/operators/concat_op.h"
#include "paddle/fluid/platform/mkldnn_helper.h"

namespace paddle {
namespace operators {

using framework::DataLayout;
using framework::Tensor;
using mkldnn::memory;
using mkldnn::primitive;
using mkldnn::concat;
using mkldnn::stream;
using platform::to_void_cast;

static void EnforceLayouts(const std::vector<const Tensor*> inputs) {
  for (auto* input : inputs) {
    const bool is_layout_correct = input->layout() == DataLayout::kMKLDNN;
    const bool is_format_defined = input->format() !=
                                   memory::format::format_undef;
    PADDLE_ENFORCE(is_layout_correct && is_format_defined,
                   "Wrong layout/format set for Input tensor");
  }
}

static memory::primitive_desc CreateMemPrimDesc(
    const Tensor& input, const mkldnn::engine& engine) {
  constexpr auto data_type = mkldnn::memory::f32;
  const auto dims = paddle::framework::vectorize2int(input.dims());
  const auto format = input.format();
  auto description = memory::desc(dims, data_type, format);
  auto mem_prim_desc = memory::primitive_desc(description, engine);
  return mem_prim_desc;
}

static mkldnn::memory::format GetDstMemFormat(
  const concat::primitive_desc& concat_pd) {
    return (memory::format)concat_pd.dst_primitive_desc().desc().data.format;
}

static platform::CPUPlace GetCpuPlace(
    const paddle::framework::ExecutionContext& ctx) {
  auto place = ctx.GetPlace();
  PADDLE_ENFORCE(paddle::platform::is_cpu_place(place),
                 "It must use CPUPlace.");
  return boost::get<platform::CPUPlace>(place);
}

static const mkldnn::engine& GetMKLDNNEngine(
  const paddle::framework::ExecutionContext& ctx) {
    auto& dev_ctx =
        ctx.template device_context<platform::MKLDNNDeviceContext>();
    return dev_ctx.GetEngine();
}

template <typename T>
class ConcatPrimitiveFactory {
 public:
  concat::primitive_desc CreateConcatPrimDescriptor(
      const std::vector<const Tensor*> multi_input, Tensor* output,
      int concat_axis, const mkldnn::engine& mkldnn_engine) {
    CreateSourcesDescriptors(multi_input, mkldnn_engine);
    auto dst_desc = CreateDstMemDescriptor(output);
    return concat::primitive_desc(dst_desc, concat_axis, srcs_pd);
  }

  concat CreateConcatPrimitive(const concat::primitive_desc& concat_pd,
                               Tensor* output, platform::CPUPlace place) {
    CreateSourcePrimitiveAts();
    auto dst_mem = CreateDstMemory(concat_pd, output, place);
    return concat(concat_pd, inputs, dst_mem);
  }

 private:
  memory::desc CreateDstMemDescriptor(Tensor* output) {
    auto dst_dims = paddle::framework::vectorize2int(output->dims());
    return memory::desc(dst_dims, platform::MKLDNNGetDataType<T>(),
                                 memory::format::any);
  }

  mkldnn::memory CreateDstMemory(const concat::primitive_desc& concat_pd,
                                 Tensor* output, platform::CPUPlace place) {
    return memory(concat_pd.dst_primitive_desc(),
                  output->mutable_data<T>(place));
  }

  void CreateSourcesDescriptors(const std::vector<const Tensor*> multi_input,
                                const mkldnn::engine& mkldnn_engine) {
    for (size_t i = 0; i < multi_input.size(); i++) {
        auto mem_prim_desc = CreateMemPrimDesc(*multi_input[i], mkldnn_engine);
        srcs_pd.push_back(mem_prim_desc);
        srcs.push_back(memory(mem_prim_desc,
                       to_void_cast(multi_input[i]->data<T>())));
    }
  }

  void CreateSourcePrimitiveAts() {
    inputs.reserve(srcs.size());
    for (size_t i = 0; i < srcs.size(); i++) {
      inputs.push_back(srcs[i]);
    }
  }

 private:
  std::vector<memory::primitive_desc> srcs_pd;
  std::vector<memory> srcs;
  std::vector<primitive::at> inputs;
};

template <typename T>
class ConcatMKLDNNOpKernel : public paddle::framework::OpKernel<T> {
 public:
  void Compute(const paddle::framework::ExecutionContext& ctx) const override {
    auto place = GetCpuPlace(ctx);
    const auto& mkldnn_engine = GetMKLDNNEngine(ctx);

    auto multi_input = ctx.MultiInput<Tensor>("X");
    EnforceLayouts(multi_input);
    Tensor* output = ctx.Output<Tensor>("Out");
    int64_t concat_axis = static_cast<int64_t>(ctx.Attr<int>("axis"));

    ConcatPrimitiveFactory<T> prim_creator;
    auto concat_pd = prim_creator.CreateConcatPrimDescriptor(multi_input,
                         output, static_cast<int>(concat_axis), mkldnn_engine);
    auto concat = prim_creator.CreateConcatPrimitive(concat_pd, output, place);
    stream(stream::kind::eager).submit({concat}).wait();

    output->set_layout(DataLayout::kMKLDNN);
    output->set_format(GetDstMemFormat(concat_pd));
  }
};
}  // namespace operators
}  // namespace paddle

namespace ops = paddle::operators;

REGISTER_OP_KERNEL(concat, MKLDNN, ::paddle::platform::CPUPlace,
                   ops::ConcatMKLDNNOpKernel<float>)
<|endoftext|>


<commit_before>#include <iostream>
#include "../tlang.h"
#include <taichi/common/util.h>
#include <taichi/math.h>
#include <taichi/common/testing.h>
#include <taichi/system/timer.h>
#include <unordered_map>

using namespace taichi;
using Tlang::measure_cpe;

struct Node {
  float x, y;
};
struct Block {
  static constexpr int size = 256;
  Node nodes[size];
};
struct Tile {
  static constexpr int size = 1024;
  Block *blocks[size];
};
constexpr int dim1 = Block::size;
constexpr int dim0 = Tile::size * dim1;
std::unordered_map<int, Tile> data;

inline float safe_access_x(int i) {
  if (data.find(i / dim0) == data.end())
    return 0;
  if (data[i / dim0].blocks[i % dim0 / dim1] == nullptr)
    return 0;
  return data[i / dim0].blocks[i % dim0 / dim1]->nodes[i % dim1].x;
}

void copy_ref() {
  for (auto &it : data) {
    auto &tile = it.second;
    for (int b = 0; b < Tile::size; b++) {
      auto block = tile.blocks[b];
      if (!block)
        continue;
      for (int n = 0; n < Block::size; n++) {
        int i = it.first * dim0 + b * dim1 + n;
        block->nodes[n].y = safe_access_x(i);
      }
    }
  }
}

void stencil_ref() {
  for (auto &it : data) {
    auto &tile = it.second;
    for (int b = 0; b < Tile::size; b++) {
      auto block = tile.blocks[b];
      if (!block)
        continue;
      for (int n = 0; n < Block::size; n++) {
        int i = it.first * dim0 + b * dim1 + n;
        block->nodes[n].y =
            (1.0f / 3) *
            (safe_access_x(i - 1) + safe_access_x(i) /* Note: can be weakened*/
             + safe_access_x(i + 1));
      }
    }
  }
}

void benchmark_layers() {
  int n = 1000000;
  int cnt = 0;
  int cnt2;

  int t = 0;

  auto test_hash_table = [&]() {
    for (int i = 0; i < n; i++) {
      t = (t + 7) & 1023;
      if (data.find(t) != data.end()) {
        cnt += 1;
      }
    }
  };

  TC_P(measure_cpe(test_hash_table, n));

  auto &tile = data.begin()->second;

  auto test_block = [&]() {
    for (int i = 0; i < n; i++) {
      t = (t + 7) & Tile::size;
      if (tile.blocks[t] != nullptr) {
        cnt += ((int64)tile.blocks[t] & 31);
      }
    }
  };

  TC_P(measure_cpe(test_block, n));

  TC_P(cnt);
}

TLANG_NAMESPACE_BEGIN

TC_TEST("stencil1d") {
  Program prog;

  Global(x, f32);
  Global(y, f32);

  layout([&] {
    auto i = Index(0);
    root.hashed(i, 1024).fixed(i, 1024).pointer().fixed(i, 256).place(x, y);
  });

  auto stencil = kernel([&] {
    Declare(i);
    For(i, x, [&] {
      x[i] = (1.0f / 3) * (y[i - 1] + y[i] + y[i + 1]);
      // y[i] = imm(0);//y[i];
      // x[i] = y[i];
    });
  });

  auto copy = kernel([&] {
    Declare(i);
    For(i, x, [&] {
      // x[i] = (1.0f / 3) * (y[i - 1] + y[i] + y[i + 1]);
      x[i] = load(y[i]);
      // y[i] = imm(0);//y[i];
      // x[i] = y[i];
    });
  });

  int total_nodes = 0;
  {
    // initialize
    int total_tiles = 0;
    int total_blocks = 0;
    for (int i = 0; i < 1024; i++) {
      if (i % 31 != 5) {
        continue;
      }
      total_tiles++;
      auto &tile = data[i];
      std::memset(&tile, 0, sizeof(tile));
      for (int j = 0; j < Tile::size; j++) {
        auto key = j % 37;
        if (!(12 <= key && key < 14)) {
          continue;
        }
        auto b = new ::Block;
        total_blocks++;
        tile.blocks[j] = b;
        for (int k = 0; k < ::Block::size; k++) {
          auto val = taichi::rand();
          b->nodes[k].x = val;
          b->nodes[k].y = 0;
          total_nodes += 1;
          auto index = i * dim0 + j * dim1 + k;
          x.val<float32>(index) = val;
        }
      }
    }
    TC_P(total_tiles);
    TC_P(total_blocks);
    TC_P(total_nodes);
  }
  // benchmark_layers();
  // TC_P(measure_cpe(stencil, total_nodes));

  for (int i = 0; i < 10; i++)
    TC_TIME(copy_ref());

  for (int i = 0; i < 10; i++)
    TC_TIME(copy());
}

TLANG_NAMESPACE_END
<commit_msg>larger benchmark; cleaner<commit_after>#include <iostream>
#include "../tlang.h"
#include <taichi/common/util.h>
#include <taichi/math.h>
#include <taichi/common/testing.h>
#include <taichi/system/timer.h>
#include <unordered_map>

using namespace taichi;
using Tlang::measure_cpe;

struct Node {
  float x, y;
};
struct Block {
  static constexpr int size = 256;
  Node nodes[size];
};
struct Tile {
  static constexpr int size = 1024;
  Block *blocks[size];
};
constexpr int dim1 = Block::size;
constexpr int dim0 = Tile::size * dim1;
std::unordered_map<int, Tile> data;

inline float safe_access_x(int i) {
  if (data.find(i / dim0) == data.end())
    return 0;
  if (data[i / dim0].blocks[i % dim0 / dim1] == nullptr)
    return 0;
  return data[i / dim0].blocks[i % dim0 / dim1]->nodes[i % dim1].x;
}

void copy_ref() {
  for (auto &it : data) {
    auto &tile = it.second;
    for (int b = 0; b < Tile::size; b++) {
      auto block = tile.blocks[b];
      if (!block)
        continue;
      for (int n = 0; n < Block::size; n++) {
        int i = it.first * dim0 + b * dim1 + n;
        block->nodes[n].y = safe_access_x(i);
      }
    }
  }
}

void stencil_ref() {
  for (auto &it : data) {
    auto &tile = it.second;
    for (int b = 0; b < Tile::size; b++) {
      auto block = tile.blocks[b];
      if (!block)
        continue;
      for (int n = 0; n < Block::size; n++) {
        int i = it.first * dim0 + b * dim1 + n;
        block->nodes[n].y =
            (1.0f / 3) *
            (safe_access_x(i - 1) + safe_access_x(i) /* Note: can be weakened*/
             + safe_access_x(i + 1));
      }
    }
  }
}

void benchmark_layers() {
  int n = 1000000;
  int cnt = 0;
  int cnt2;

  int t = 0;

  auto test_hash_table = [&]() {
    for (int i = 0; i < n; i++) {
      t = (t + 7) & 1023;
      if (data.find(t) != data.end()) {
        cnt += 1;
      }
    }
  };

  TC_P(measure_cpe(test_hash_table, n));

  auto &tile = data.begin()->second;

  auto test_block = [&]() {
    for (int i = 0; i < n; i++) {
      t = (t + 7) & Tile::size;
      if (tile.blocks[t] != nullptr) {
        cnt += ((int64)tile.blocks[t] & 31);
      }
    }
  };

  TC_P(measure_cpe(test_block, n));

  TC_P(cnt);
}

TLANG_NAMESPACE_BEGIN

TC_TEST("stencil1d") {
  Program prog;

  Global(x, f32);
  Global(y, f32);

  layout([&] {
    auto i = Index(0);
    root.hashed(i, 8192).fixed(i, 1024).pointer().fixed(i, 256).place(x, y);
  });

  auto stencil = kernel([&] {
    Declare(i);
    For(i, x, [&] {
      x[i] = (1.0f / 3) * (y[i - 1] + y[i] + y[i + 1]);
    });
  });

  auto copy = kernel([&] {
    Declare(i);
    For(i, x, [&] {
      x[i] = y[i];
    });
  });

  int total_nodes = 0;
  {
    // initialize
    int total_tiles = 0;
    int total_blocks = 0;
    for (int i = 0; i < 8192; i++) {
      if (i % 31 != 5) {
        continue;
      }
      total_tiles++;
      auto &tile = data[i];
      std::memset(&tile, 0, sizeof(tile));
      for (int j = 0; j < Tile::size; j++) {
        auto key = j % 37;
        if (!(12 <= key && key < 14)) {
          continue;
        }
        auto b = new ::Block;
        total_blocks++;
        tile.blocks[j] = b;
        for (int k = 0; k < ::Block::size; k++) {
          auto val = taichi::rand();
          b->nodes[k].x = val;
          b->nodes[k].y = 0;
          total_nodes += 1;
          auto index = i * dim0 + j * dim1 + k;
          x.val<float32>(index) = val;
        }
      }
    }
    TC_P(total_tiles);
    TC_P(total_blocks);
    TC_P(total_nodes);
  }
  // benchmark_layers();
  // TC_P(measure_cpe(stencil, total_nodes));

  for (int i = 0; i < 10; i++)
    TC_TIME(copy_ref());

  for (int i = 0; i < 10; i++)
    TC_TIME(copy());
}

TLANG_NAMESPACE_END
<|endoftext|>


<commit_before>#include <iostream>

#include "dispatch.hpp"

int main()
{
  enum
  {
    NORMAL,
    INVALID
  } state(NORMAL);

  std::cout <<
    gnr::dispatch(
      state,
      []() -> decltype(auto) { return "NORMAL"; },
      []() -> decltype(auto) { return "INVALID"; }
    ) <<
    std::endl;

  std::cout << gnr::select(1, 0, 1, 4) << std::endl;

  std::cout <<
    gnr::dispatch2(
      state = INVALID,
      NORMAL,
      []() -> decltype(auto) { return "NORMAL"; },
      INVALID,
      []() -> decltype(auto) { return "INVALID"; }
    ) <<
    std::endl;

  return 0;
}
<commit_msg>some fixes<commit_after>#include <iostream>

#include "dispatch.hpp"

int main()
{
  enum
  {
    NORMAL,
    INVALID
  } state(NORMAL);

  std::cout <<
    gnr::dispatch(
      state,
      []() -> decltype(auto) { return "NORMAL"; },
      []() -> decltype(auto) { return "INVALID"; }
    ) <<
    std::endl;

  std::cout << gnr::select(1, 0, 1, 4) << std::endl;

  std::cout <<
    gnr::dispatch2(
      state = INVALID,
      NORMAL,
      []{ return "NORMAL"; },
      INVALID,
      []{ return "INVALID"; }
    ) <<
    std::endl;

  return 0;
}
<|endoftext|>


<commit_before>#include <osg/MatrixTransform>

#include "Skybox.h"

// Konstruktor zum Anlegen der Skybox
ph::Skybox::Skybox(const int height, const int width) {
    // Übergeben der Länge/Breite
    this->height = height;
    this->width = width;

    setReferenceFrame(Transform::ABSOLUTE_RF);
    setCullingActive(false);

    osg::StateSet* stateSet = getOrCreateStateSet();
    // Tiefenpuffer; Objekte verschwinden nicht einfach, wenn sich auf Rand
    // der Skybox treffen
    stateSet->setAttributeAndModes(new Depth(Depth::LEQUAL, 1.0f, 1.0f));
    // Licht ausmachen
    stateSet->setMode(GL_LIGHTING, StateAttribute::OFF);
    // Culling für Flächen außerhalb der Skybox
    stateSet->setMode(GL_CULL_FACE, StateAttribute::OFF);
    //ss->setRenderBinDetails( 5, "RenderBin" );

    // Anlegen der Rechtecke
    createRectangles();
}

void ph::Skybox::createRectangles() {

    /* Rotationen werde so durchgeführt, dass man vom Mittelpunkt der Box aus jeweils korrekte
       Sicht auf die Texturen hat, also (0,0) "unten links" ist und (1,1) "oben rechts" */

    // creating and placing front-Rectangle
    this->front = new Rectangle(this->height, this->width);
    ref_ptr<MatrixTransform> rec_trans_front = new MatrixTransform();
    // verschieben um hoehe/2 in y
    rec_trans_front->setMatrix( Matrix::translate(0.0, this->height/2.0, 0.0));
    rec_trans_front->addChild(this->front.get());
    this->addChild(rec_trans_front.get());

    // creating and placing back-Rectangle
    this->back = new Rectangle(this->height, this->width);
    ref_ptr<MatrixTransform> rec_trans_back = new MatrixTransform();
    // zuerst rotieren. pi um z, dann verschieben um -hoehe/2 in y
    rec_trans_back->setMatrix( Matrix::rotate(PI,Vec3(0.0,0.0,1.0))*
                        Matrix::translate(0.0, -this->height/2.0, 0.0));
    rec_trans_back->addChild(this->back.get());
    this->addChild(rec_trans_back.get());

    // creating and placing left-Rectangle
    this->left = new Rectangle(this->height, this->width);
    ref_ptr<MatrixTransform> rec_trans_left = new MatrixTransform();
    // zuerst rotieren: pi/2 um z, dann verschieben um -hoehe/2 in x
    rec_trans_left->setMatrix( Matrix::rotate(PI_2,Vec3(0.0,0.0,1.0))*
                        Matrix::translate(-this->height/2.0, 0.0, 0.0));
    rec_trans_left->addChild(this->left.get());
    this->addChild(rec_trans_left.get());

    // creating and placing right-Rectangle
    this->right = new Rectangle(this->height, this->width);
    ref_ptr<MatrixTransform> rec_trans_right = new MatrixTransform();
    // zuerst rotieren: -pi/2 um z, dann verschieben um hoehe/2 in x
    rec_trans_right->setMatrix( Matrix::rotate(-PI_2,Vec3(0.0,0.0,1.0))*
                        Matrix::translate(this->height/2.0, 0.0, 0.0));
    rec_trans_right->addChild(this->right.get());
    this->addChild(rec_trans_right.get());

    // creating and placing top-Rectangle
    this->top = new Rectangle(this->height, this->height);
    ref_ptr<MatrixTransform> rec_trans_top = new MatrixTransform();
    // zuerst rotieren: pi/2 um x, dann verschieben um breite/2 in z
    rec_trans_top->setMatrix( Matrix::rotate(PI_2,Vec3(1.0,0.0,0.0))*
                        Matrix::translate(0.0, 0.0, this->width/2.0));
    rec_trans_top->addChild(this->top.get());
    this->addChild(rec_trans_top.get());

    // creating and placing bottom-Rectangle
    this->bottom = new Rectangle(this->height, this->height);
    ref_ptr<MatrixTransform> rec_trans_bottom = new MatrixTransform();
    // zuerst rotieren: -pi/2 um x, dann verschieben um -breite/2 in z
    rec_trans_bottom->setMatrix( Matrix::rotate(-PI_2,Vec3(1.0,0.0,0.0))*
                        Matrix::translate(0.0, 0.0, -this->width/2.0));
    rec_trans_bottom->addChild(this->bottom.get());
    this->addChild(rec_trans_bottom.get());
}

// setting texture on the rectangle given bei the Position enumeration
void ph::Skybox::setTexture(const Position pos, const int textureNumber, const string filename) {
    Rectangle* rec;
    switch (pos) {
    case FRONT: rec = this->front; break;
    case BACK: rec = this->back; break;
    case TOP: rec = this->top; break;
    case BOTTOM: rec = this->bottom; break;
    case LEFT: rec = this->left; break;
    case RIGHT: rec = this->right;break;
    }

    rec->setTexture(textureNumber,filename);
}

// clamping an object to the skybox
void ph::Skybox::clampObjectToSkybox(ref_ptr<MatrixTransform>& mt) {
    this->addChild(mt.get());
}

/* aus: OSG Cookbook, pp. 256ff, Funktionen für Funktionalität: Verschieben der Skybox
   geerbte Funktionen aus der Superklasse Transform zum Verschieben der Skybox mit
   dem Auge */
bool ph::Skybox::computeLocalToWorldMatrix( Matrix& matrix, NodeVisitor* nv ) const
{
    if ( nv && nv->getVisitorType() == NodeVisitor::CULL_VISITOR )
    {
        osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>( nv );
        matrix.preMult( Matrix::translate(cv->getEyeLocal()) );
        return true;
    }
    else
        return Transform::computeLocalToWorldMatrix( matrix, nv );
}

bool ph::Skybox::computeWorldToLocalMatrix( Matrix& matrix, NodeVisitor* nv ) const
{
    if ( nv && nv->getVisitorType() == NodeVisitor::CULL_VISITOR )
    {
        osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>( nv );
        matrix.postMult( Matrix::translate(-cv->getEyeLocal()) );
        return true;
    }
    else
        return Transform::computeWorldToLocalMatrix( matrix, nv );
}
<commit_msg>minor adjustment on culling<commit_after>#include <osg/MatrixTransform>

#include "Skybox.h"

// Konstruktor zum Anlegen der Skybox
ph::Skybox::Skybox(const int height, const int width) {
    // Übergeben der Länge/Breite
    this->height = height;
    this->width = width;

    setReferenceFrame(Transform::ABSOLUTE_RF);
    setCullingActive(false);

    osg::StateSet* stateSet = this->getOrCreateStateSet();
    // Tiefenpuffer; Objekte verschwinden nicht einfach, wenn sich auf Rand
    // der Skybox treffen
    stateSet->setAttributeAndModes(new Depth(Depth::LEQUAL, 1.0f, 1.0f));
    // Licht ausmachen
    stateSet->setMode(GL_LIGHTING, StateAttribute::OFF);
    // Culling für Flächen außerhalb der Skybox
    stateSet->setMode(GL_CULL_FACE, StateAttribute::OFF);

    // Anlegen der Rechtecke
    createRectangles();
}

void ph::Skybox::createRectangles() {

    /* Rotationen werde so durchgeführt, dass man vom Mittelpunkt der Box aus jeweils korrekte
       Sicht auf die Texturen hat, also (0,0) "unten links" ist und (1,1) "oben rechts" */

    // creating and placing front-Rectangle
    this->front = new Rectangle(this->height, this->width);
    ref_ptr<MatrixTransform> rec_trans_front = new MatrixTransform();
    // verschieben um hoehe/2 in y
    rec_trans_front->setMatrix( Matrix::translate(0.0, this->height/2.0, 0.0));
    rec_trans_front->addChild(this->front.get());
    this->addChild(rec_trans_front.get());

    // creating and placing back-Rectangle
    this->back = new Rectangle(this->height, this->width);
    ref_ptr<MatrixTransform> rec_trans_back = new MatrixTransform();
    // zuerst rotieren. pi um z, dann verschieben um -hoehe/2 in y
    rec_trans_back->setMatrix( Matrix::rotate(PI,Vec3(0.0,0.0,1.0))*
                        Matrix::translate(0.0, -this->height/2.0, 0.0));
    rec_trans_back->addChild(this->back.get());
    this->addChild(rec_trans_back.get());

    // creating and placing left-Rectangle
    this->left = new Rectangle(this->height, this->width);
    ref_ptr<MatrixTransform> rec_trans_left = new MatrixTransform();
    // zuerst rotieren: pi/2 um z, dann verschieben um -hoehe/2 in x
    rec_trans_left->setMatrix( Matrix::rotate(PI_2,Vec3(0.0,0.0,1.0))*
                        Matrix::translate(-this->height/2.0, 0.0, 0.0));
    rec_trans_left->addChild(this->left.get());
    this->addChild(rec_trans_left.get());

    // creating and placing right-Rectangle
    this->right = new Rectangle(this->height, this->width);
    ref_ptr<MatrixTransform> rec_trans_right = new MatrixTransform();
    // zuerst rotieren: -pi/2 um z, dann verschieben um hoehe/2 in x
    rec_trans_right->setMatrix( Matrix::rotate(-PI_2,Vec3(0.0,0.0,1.0))*
                        Matrix::translate(this->height/2.0, 0.0, 0.0));
    rec_trans_right->addChild(this->right.get());
    this->addChild(rec_trans_right.get());

    // creating and placing top-Rectangle
    this->top = new Rectangle(this->height, this->height);
    ref_ptr<MatrixTransform> rec_trans_top = new MatrixTransform();
    // zuerst rotieren: pi/2 um x, dann verschieben um breite/2 in z
    rec_trans_top->setMatrix( Matrix::rotate(PI_2,Vec3(1.0,0.0,0.0))*
                        Matrix::translate(0.0, 0.0, this->width/2.0));
    rec_trans_top->addChild(this->top.get());
    this->addChild(rec_trans_top.get());

    // creating and placing bottom-Rectangle
    this->bottom = new Rectangle(this->height, this->height);
    ref_ptr<MatrixTransform> rec_trans_bottom = new MatrixTransform();
    // zuerst rotieren: -pi/2 um x, dann verschieben um -breite/2 in z
    rec_trans_bottom->setMatrix( Matrix::rotate(-PI_2,Vec3(1.0,0.0,0.0))*
                        Matrix::translate(0.0, 0.0, -this->width/2.0));
    rec_trans_bottom->addChild(this->bottom.get());
    this->addChild(rec_trans_bottom.get());
}

// setting texture on the rectangle given bei the Position enumeration
void ph::Skybox::setTexture(const Position pos, const int textureNumber, const string filename) {
    Rectangle* rec;
    switch (pos) {
    case FRONT: rec = this->front; break;
    case BACK: rec = this->back; break;
    case TOP: rec = this->top; break;
    case BOTTOM: rec = this->bottom; break;
    case LEFT: rec = this->left; break;
    case RIGHT: rec = this->right;break;
    }

    rec->setTexture(textureNumber,filename);
}

// clamping an object to the skybox
void ph::Skybox::clampObjectToSkybox(ref_ptr<MatrixTransform>& mt) {
    this->addChild(mt.get());
}

/* aus: OSG Cookbook, pp. 256ff, Funktionen für Funktionalität: Verschieben der Skybox
   geerbte Funktionen aus der Superklasse Transform zum Verschieben der Skybox mit
   dem Auge */
bool ph::Skybox::computeLocalToWorldMatrix( Matrix& matrix, NodeVisitor* nv ) const
{
    if ( nv && nv->getVisitorType() == NodeVisitor::CULL_VISITOR )
    {
        osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>( nv );
        matrix.preMult( Matrix::translate(cv->getEyeLocal()) );
        return true;
    }
    else
        return Transform::computeLocalToWorldMatrix( matrix, nv );
}

bool ph::Skybox::computeWorldToLocalMatrix( Matrix& matrix, NodeVisitor* nv ) const
{
    if ( nv && nv->getVisitorType() == NodeVisitor::CULL_VISITOR )
    {
        osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>( nv );
        matrix.postMult( Matrix::translate(-cv->getEyeLocal()) );
        return true;
    }
    else
        return Transform::computeWorldToLocalMatrix( matrix, nv );
}
<|endoftext|>


<commit_before>#include <netlib/socket.h>

#include <netinet/tcp.h> // TCP_NODELAY
#include <strings.h> // bzero()
#include <unistd.h> // close()
#include <sys/socket.h> // setsockopt(), accept4(), listen(), bind(), shutdown()

#include <netlib/logging.h>
#include <netlib/socket_address.h>
#include <netlib/socket_operation.h>

using netlib::Socket;

Socket::~Socket()
{
	::close(socket_fd_);
}

// int bind(int sockfd, const struct sockaddr *address, socklen_t address_length);
// When a socket is created with socket(2), it has no address assigned to it.
// ::bind() assigns the address specified by address to the socket referred to by
// the file descriptor sockfd. address_length specifies the size, in bytes, of the
// address structure pointed to by address.
// On success, 0 is returned. On error, -1 is returned, and errno is set.
// Assign local_address object's address_ to this Socket's object's socket_fd_.
void Socket::Bind(const SocketAddress &local_address)
{
	const struct sockaddr *address = local_address.socket_address();
	int ret = ::bind(socket_fd_, address, static_cast<socklen_t>(sizeof address));
	if(ret == -1)
	{
		LOG_FATAL("bind(): FATAL");
	}
}

// int listen(int sockfd, int backlog);
// listen() marks the socket `sockfd` as a passive socket, that is, as a socket that will
// be used to accept incoming connection requests using accept(2).
// backlog defines the maximum length to which the queue of pending connections
// for sockfd may grow. If a connection request arrives when the queue is full,
// the client may receive an error with an indication of ECONNREFUSED or, if
// the underlying protocol supports retransmission, the request may be ignored so
// that a later reattempt at connection succeeds.
// On success, 0 is returned. On error, -1 is returned and errno is set.
// Mark socket_fd_ as a passive socket(i.e., accept connections).
void Socket::Listen()
{
	// SOMAXCONN: Maximum queue length specifiable by listen.
	if(::listen(socket_fd_, SOMAXCONN) == -1)
	{
		LOG_FATAL("listen(): FATAL");
	}
}

// int accept4(int sockfd, struct sockaddr *address, socklen_t *addrlen, int flags);
// accept() extracts the first connection request on the queue of pending connections
// for the listening socket, sockfd, creates a new connected socket, and returns a new
// file descriptor referring to that socket. sockfd is unaffected by this call.
// sockfd is a socket that has been created with socket(2), bound to a local address
// with bind(2), and is listening for connections after a listen(2).
// address is a pointer to a sockaddr structure. This structure is filled in with the
// address of the peer socket. When address is NULL, nothing is filled in and
// addrlen should be NULL.
// addrlen is a value-result argument: the caller must initialize it to contain the size
// (in bytes) of the structure pointed to by address; on return it will contain the size
// of the peer address.
// Return a nonnegative integer that is a descriptor for the accepted socket on success.
// On error, -1 is returned, and errno is set.
// Return the file descriptor for the new accepted connection.
// Store the peer's address to `*peer_address` object.
int Socket::Accept(SocketAddress &peer_address)
{
	struct sockaddr_in address;
	bzero(&address, sizeof address);
	socklen_t address_length = static_cast<socklen_t>(sizeof address);
	int connected_fd = ::accept4(socket_fd_,
	                             nso::CastToNonConstsockaddr(&address),
	                             &address_length,
	                             SOCK_NONBLOCK | SOCK_CLOEXEC);
	if(connected_fd == -1)
	{
		int saved_errno = errno;
		LOG_ERROR("accept(): ERROR");
		switch(saved_errno)
		{
		// EAGAIN or EWOULDBLOCK
		// The socket is marked nonblocking and no connections are present to be accepted.
		// A portable application should check for both possibilities.
		case EAGAIN:
		// case EWOULDBLOCK: // socket.cc:89:3: error: duplicate case value
		// accept()/accept4() passes pending network errors on the new socket as an error
		// code from accept(). The application should detect the network errors defined
		// for the protocol after accept() and treat them like EAGAIN by retrying. For
		// TCP/IP: ENETDOWN, EPROTO, ENOPROTOOPT, EHOSTDOWN,
		// ENONET, EHOSTUNREACH, EOPNOTSUPP, and ENETUNREACH.
		case ENETDOWN:
		case EPROTO: // Protocol error.
		case ENOPROTOOPT:
		case EHOSTDOWN:
		case ENONET:
		case EHOSTUNREACH:
		case EOPNOTSUPP: // The socket is not of type SOCK_STREAM.
		case ENETUNREACH:
		// A connection has been aborted.
		case ECONNABORTED:
		// accept() was interrupted by a signal that was caught before a connection arrived.
		case EINTR:
		// Firewall rules forbid connection.
		case EPERM:
		// The per-process limit of open file descriptors has been reached.
		case EMFILE:
			// Temporary errors: ignore error.
			errno = saved_errno;
			break;
		// The descriptor is invalid.
		case EBADF:
		// The addr argument is not in a writable part of the user address space.
		case EFAULT:
		// `socket` is not listening, `addrlen` is invalid, or `flags` is invalid.
		case EINVAL:
		// The system limit on the total number of open files has been reached.
		case ENFILE:
		// ENOBUFS, ENOMEM
		// Not enough free memory. This often means that the memory allocation is
		// limited by the socket buffer limits, not by the system memory.
		case ENOBUFS:
		case ENOMEM:
		// The descriptor references a file, not a socket.
		case ENOTSOCK:
			LOG_FATAL("unexpected error of ::accept");
		default:
			LOG_FATAL("unknown error of ::accept");
		}
	}
	else if(connected_fd >= 0)
	{
		peer_address.set_socket_address(address);
	}
	return connected_fd;
}

// int shutdown(int sockfd, int how);
// On success, 0 is returned. On error, -1 is returned and errno is set.
void Socket::ShutdownOnWrite()
{
	if(::shutdown(socket_fd_, SHUT_WR) == -1)
	{
		LOG_ERROR("shutdown(): ERROR");
	}
}

// int setsockopt(int sockfd, int level, int optname,
//                const void *option_value, socklen_t optlen);
// sockfd must refer to an open socket descriptor.
// level specifies the code that interprets the option: the general socket code
// or some protocol-specific code(e.g., IPv4, IPv6, TCP).
// option_value is a pointer to a variable from which the new value of the option is fetched.
// optlen is the size of this variable.
// On success, 0 is returned. On error, -1 is returned, and errno is set.
void Socket::SetReuseAddress(bool on)
{
	int option_value = on ? 1 : 0;
	// SOL_SOCKET: manipulate options at the sockets API level.
	int ret = ::setsockopt(socket_fd_, SOL_SOCKET, SO_REUSEADDR,
	                       &option_value, static_cast<socklen_t>(sizeof option_value));
	if(ret == -1 && on)
	{
		LOG_ERROR("setsockopt(SO_REUSEADDR): ERROR");
	}
}
void Socket::SetReusePort(bool on)
{
#ifdef SO_REUSEPORT
	int option_value = on ? 1 : 0;
	int ret = ::setsockopt(socket_fd_, SOL_SOCKET, SO_REUSEPORT,
	                       &option_value, static_cast<socklen_t>(sizeof option_value));
	if(ret == -1 && on)
	{
		LOG_ERROR("SO_REUSEPORT error.");
	}
#else
	if(on)
	{
		LOG_INFO("SO_REUSEPORT is not supported.");
	}
#endif
}
void Socket::SetTcpKeepAlive(bool on)
{
	int option_value = on ? 1 : 0;
	int ret = ::setsockopt(socket_fd_, SOL_SOCKET, SO_KEEPALIVE,
	                       &option_value, static_cast<socklen_t>(sizeof option_value));
	if(ret == -1 && on)
	{
		LOG_ERROR("setsockopt(SO_KEEPALIVE): ERROR");
	}
}
void Socket::SetTcpNoDelay(bool on)
{
	int option_value = on ? 1 : 0;
	// IPPROTO_TCP is used for TCP protocol.
	int ret = ::setsockopt(socket_fd_, IPPROTO_TCP, TCP_NODELAY,
	                       &option_value, static_cast<socklen_t>(sizeof option_value));
	if(ret == -1 && on)
	{
		LOG_ERROR("SetTcpNoDelay error");
	}
}
<commit_msg>fix: use (sizeof *address) not (sizeof address) in Bind()<commit_after>#include <netlib/socket.h>

#include <netinet/tcp.h> // TCP_NODELAY
#include <strings.h> // bzero()
#include <unistd.h> // close()
#include <sys/socket.h> // setsockopt(), accept4(), listen(), bind(), shutdown()

#include <netlib/logging.h>
#include <netlib/socket_address.h>
#include <netlib/socket_operation.h>

using netlib::Socket;

Socket::~Socket()
{
	::close(socket_fd_);
}

// int bind(int sockfd, const struct sockaddr *address, socklen_t address_length);
// When a socket is created with socket(2), it has no address assigned to it.
// ::bind() assigns the address specified by address to the socket referred to by
// the file descriptor sockfd. address_length specifies the size, in bytes, of the
// address structure pointed to by address.
// On success, 0 is returned. On error, -1 is returned, and errno is set.
// Assign local_address object's address_ to this Socket's object's socket_fd_.
void Socket::Bind(const SocketAddress &local_address)
{
	const struct sockaddr *address = local_address.socket_address();
	// NOTE: sizeof address = 8, sizeof *address = 16! sizeof structure, not pointer!
	int ret = ::bind(socket_fd_, address, static_cast<socklen_t>(sizeof *address));
	if(ret == -1)
	{
		LOG_FATAL("bind(): FATAL");
	}
}

// int listen(int sockfd, int backlog);
// listen() marks the socket `sockfd` as a passive socket, that is, as a socket that will
// be used to accept incoming connection requests using accept(2).
// backlog defines the maximum length to which the queue of pending connections
// for sockfd may grow. If a connection request arrives when the queue is full,
// the client may receive an error with an indication of ECONNREFUSED or, if
// the underlying protocol supports retransmission, the request may be ignored so
// that a later reattempt at connection succeeds.
// On success, 0 is returned. On error, -1 is returned and errno is set.
// Mark socket_fd_ as a passive socket(i.e., accept connections).
void Socket::Listen()
{
	// SOMAXCONN: Maximum queue length specifiable by listen.
	if(::listen(socket_fd_, SOMAXCONN) == -1)
	{
		LOG_FATAL("listen(): FATAL");
	}
}

// int accept4(int sockfd, struct sockaddr *address, socklen_t *addrlen, int flags);
// accept() extracts the first connection request on the queue of pending connections
// for the listening socket, sockfd, creates a new connected socket, and returns a new
// file descriptor referring to that socket. sockfd is unaffected by this call.
// sockfd is a socket that has been created with socket(2), bound to a local address
// with bind(2), and is listening for connections after a listen(2).
// address is a pointer to a sockaddr structure. This structure is filled in with the
// address of the peer socket. When address is NULL, nothing is filled in and
// addrlen should be NULL.
// addrlen is a value-result argument: the caller must initialize it to contain the size
// (in bytes) of the structure pointed to by address; on return it will contain the size
// of the peer address.
// Return a nonnegative integer that is a descriptor for the accepted socket on success.
// On error, -1 is returned, and errno is set.
// Return the file descriptor for the new accepted connection.
// Store the peer's address to `*peer_address` object.
int Socket::Accept(SocketAddress &peer_address)
{
	struct sockaddr_in address;
	bzero(&address, sizeof address);
	socklen_t address_length = static_cast<socklen_t>(sizeof address);
	int connected_fd = ::accept4(socket_fd_,
	                             nso::CastToNonConstsockaddr(&address),
	                             &address_length,
	                             SOCK_NONBLOCK | SOCK_CLOEXEC);
	if(connected_fd == -1)
	{
		int saved_errno = errno;
		LOG_ERROR("accept(): ERROR");
		switch(saved_errno)
		{
		// EAGAIN or EWOULDBLOCK
		// The socket is marked nonblocking and no connections are present to be accepted.
		// A portable application should check for both possibilities.
		case EAGAIN:
		// case EWOULDBLOCK: // socket.cc:89:3: error: duplicate case value
		// accept()/accept4() passes pending network errors on the new socket as an error
		// code from accept(). The application should detect the network errors defined
		// for the protocol after accept() and treat them like EAGAIN by retrying. For
		// TCP/IP: ENETDOWN, EPROTO, ENOPROTOOPT, EHOSTDOWN,
		// ENONET, EHOSTUNREACH, EOPNOTSUPP, and ENETUNREACH.
		case ENETDOWN:
		case EPROTO: // Protocol error.
		case ENOPROTOOPT:
		case EHOSTDOWN:
		case ENONET:
		case EHOSTUNREACH:
		case EOPNOTSUPP: // The socket is not of type SOCK_STREAM.
		case ENETUNREACH:
		// A connection has been aborted.
		case ECONNABORTED:
		// accept() was interrupted by a signal that was caught before a connection arrived.
		case EINTR:
		// Firewall rules forbid connection.
		case EPERM:
		// The per-process limit of open file descriptors has been reached.
		case EMFILE:
			// Temporary errors: ignore error.
			errno = saved_errno;
			break;
		// The descriptor is invalid.
		case EBADF:
		// The addr argument is not in a writable part of the user address space.
		case EFAULT:
		// `socket` is not listening, `addrlen` is invalid, or `flags` is invalid.
		case EINVAL:
		// The system limit on the total number of open files has been reached.
		case ENFILE:
		// ENOBUFS, ENOMEM
		// Not enough free memory. This often means that the memory allocation is
		// limited by the socket buffer limits, not by the system memory.
		case ENOBUFS:
		case ENOMEM:
		// The descriptor references a file, not a socket.
		case ENOTSOCK:
			LOG_FATAL("unexpected error of ::accept");
		default:
			LOG_FATAL("unknown error of ::accept");
		}
	}
	else if(connected_fd >= 0)
	{
		peer_address.set_socket_address(address);
	}
	return connected_fd;
}

// int shutdown(int sockfd, int how);
// On success, 0 is returned. On error, -1 is returned and errno is set.
void Socket::ShutdownOnWrite()
{
	if(::shutdown(socket_fd_, SHUT_WR) == -1)
	{
		LOG_ERROR("shutdown(): ERROR");
	}
}

// int setsockopt(int sockfd, int level, int optname,
//                const void *option_value, socklen_t optlen);
// sockfd must refer to an open socket descriptor.
// level specifies the code that interprets the option: the general socket code
// or some protocol-specific code(e.g., IPv4, IPv6, TCP).
// option_value is a pointer to a variable from which the new value of the option is fetched.
// optlen is the size of this variable.
// On success, 0 is returned. On error, -1 is returned, and errno is set.
void Socket::SetReuseAddress(bool on)
{
	int option_value = on ? 1 : 0;
	// SOL_SOCKET: manipulate options at the sockets API level.
	int ret = ::setsockopt(socket_fd_, SOL_SOCKET, SO_REUSEADDR,
	                       &option_value, static_cast<socklen_t>(sizeof option_value));
	if(ret == -1 && on)
	{
		LOG_ERROR("setsockopt(SO_REUSEADDR): ERROR");
	}
}
void Socket::SetReusePort(bool on)
{
#ifdef SO_REUSEPORT
	int option_value = on ? 1 : 0;
	int ret = ::setsockopt(socket_fd_, SOL_SOCKET, SO_REUSEPORT,
	                       &option_value, static_cast<socklen_t>(sizeof option_value));
	if(ret == -1 && on)
	{
		LOG_ERROR("SO_REUSEPORT error.");
	}
#else
	if(on)
	{
		LOG_INFO("SO_REUSEPORT is not supported.");
	}
#endif
}
void Socket::SetTcpKeepAlive(bool on)
{
	int option_value = on ? 1 : 0;
	int ret = ::setsockopt(socket_fd_, SOL_SOCKET, SO_KEEPALIVE,
	                       &option_value, static_cast<socklen_t>(sizeof option_value));
	if(ret == -1 && on)
	{
		LOG_ERROR("setsockopt(SO_KEEPALIVE): ERROR");
	}
}
void Socket::SetTcpNoDelay(bool on)
{
	int option_value = on ? 1 : 0;
	// IPPROTO_TCP is used for TCP protocol.
	int ret = ::setsockopt(socket_fd_, IPPROTO_TCP, TCP_NODELAY,
	                       &option_value, static_cast<socklen_t>(sizeof option_value));
	if(ret == -1 && on)
	{
		LOG_ERROR("SetTcpNoDelay error");
	}
}
<|endoftext|>


<commit_before>#include "MathematicalProgram.h"
#include "Optimization.h"

namespace Drake {
MathematicalProgramInterface::~MathematicalProgramInterface() { }

namespace {

class MathematicalProgram : public MathematicalProgramInterface {
 public:
  virtual ~MathematicalProgram() { }

/* these would be used to fill out the optimization hierarchy prototyped
   below
   virtual MathematicalProgramInterface* addIntegerVariable() { return new
   MathematicalProgram; }

   virtual MathematicalProgramInterface* addLinearCost() { return new
   MathematicalProgram; }
   virtual MathematicalProgramInterface* addQuadraticCost() { return new
   MathematicalProgram; }
   virtual MathematicalProgramInterface* addCost() { return new
   MathematicalProgram; }

   virtual MathematicalProgramInterface* addSumsOfSquaresConstraint() { return new
   MathematicalProgram; }
   virtual MathematicalProgramInterface* addLinearMatrixInequalityConstraint() {
   return new MathematicalProgram; }
   virtual MathematicalProgramInterface* addSecondOrderConeConstraint() { return new
   MathematicalProgram; }
   virtual MathematicalProgramInterface* addComplementarityConstraint() { return new
   MathematicalProgram; };
*/
  virtual MathematicalProgramInterface* addGenericObjective() override {
    return new MathematicalProgram;
  };
  virtual MathematicalProgramInterface* addGenericConstraint() override {
    return new MathematicalProgram;
  };
  virtual MathematicalProgramInterface* addLinearConstraint() override {
    return new MathematicalProgram;
  };
  virtual MathematicalProgramInterface* addLinearEqualityConstraint() override {
    return new MathematicalProgram;
  };
  virtual bool solve(OptimizationProblem& prog) const override {
    throw std::runtime_error("not implemented yet");
  }
};

class NonlinearProgram : public MathematicalProgram {
 public:
    virtual MathematicalProgramInterface* addGenericObjective() override {
      return new NonlinearProgram;
    };
    virtual MathematicalProgramInterface* addGenericConstraint() override {
      return new NonlinearProgram;
    };
    virtual MathematicalProgramInterface* addLinearConstraint() override {
      return new NonlinearProgram;
    };
    virtual MathematicalProgramInterface* addLinearEqualityConstraint() override {
      return new NonlinearProgram;
    };

  virtual bool solve(OptimizationProblem& prog) const override {
    if (snopt_solver.available()) { return snopt_solver.solve(prog); }
    return MathematicalProgram::solve(prog);
  }

 private:
  MathematicalProgramSNOPTSolver snopt_solver;
};

/*  // Prototype of the more complete optimization problem class hiearchy (to
    be implemented only as needed)
    struct MixedIntegerNonlinearProgram : public MathematicalProgramInterface {};
    struct MixedIntegerSemidefiniteProgram : public
    MixedIntegerNonlinearProgram {};
    struct MixedIntegerSecondOrderConeProgram : public
    MixedIntegerSemidefiniteProgram {};
    struct MixedIntegerQuadraticProgram : public
    MixedIntegerSecondOrderConeProgram {};
    struct MixedIntegerLinearProgram : public MixedIntegerQuadraticProgram {};

    struct NonlinearProgram : public MixedIntegerNonlinearProgram {};
    struct SemidefiniteProgram : public NonlinearProgram, public
    MixedIntegerSemidefiniteProgram {};
    struct SecondOrderConeProgram : public SemidefiniteProgram, public
    MixedIntegerSecondOrderConeProgram {};
    struct QuadraticProgram : public SecondOrderConeProgram, public
    MixedIntegerQuadraticProgram {};
    struct LinearProgram : public QuadraticProgram, public
    MixedIntegerLinearProgram {
    virtual MathematicalProgramInterface* addLinearEqualityConstraint() { return new
    LinearProgram; };
    virtual MathematicalProgramInterface* addLinearInequalityConstraint() { return
    new LinearProgram; };
    };

    struct NonlinearComplementarityProblem : public NonlinearProgram {};
    struct LinearComplementarityProblem : public
    NonlinearComplementarityProblem {};
*/

class LeastSquares
    : public NonlinearProgram {  // public LinearProgram, public
 public:
  // LinearComplementarityProblem
  virtual MathematicalProgramInterface* addLinearEqualityConstraint() override {
    return new LeastSquares;
  };
  virtual bool solve(OptimizationProblem& prog) const override {
    size_t num_constraints = 0;
    for (auto const& binding : prog.getLinearEqualityConstraints()) {
      num_constraints += binding.getConstraint()->getMatrix().rows();
    }

    Eigen::MatrixXd Aeq = Eigen::MatrixXd::Zero(
        num_constraints, prog.getNumVars());  // todo: use a sparse matrix here?
    Eigen::VectorXd beq(num_constraints);

    size_t constraint_index = 0;
    for (auto const& binding :  prog.getLinearEqualityConstraints()) {
      auto const& c = binding.getConstraint();
      size_t n = c->getMatrix().rows();
      size_t var_index = 0;
      for (const DecisionVariableView& v : binding.getVariableList()) {
        Aeq.block(constraint_index, v.index(), n, v.size()) =
            c->getMatrix().middleCols(var_index, v.size());
        var_index += v.size();
      }
      beq.segment(constraint_index, n) =
          c->getLowerBound();  // = c->getUpperBound() since it's an equality
      // constraint
      constraint_index += n;
    }

    // least-squares solution
    prog.setDecisionVariableValues(
        Aeq.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(beq));
    return true;
  }
};
}

std::shared_ptr<MathematicalProgramInterface>
MathematicalProgramInterface::getLeastSquaresProgram() {
  return std::shared_ptr<MathematicalProgramInterface>(new LeastSquares);
}

MathematicalProgramSolverInterface::~MathematicalProgramSolverInterface() { }

}
<commit_msg>Added debug print statement.<commit_after>#include "MathematicalProgram.h"
#include "Optimization.h"

namespace Drake {
MathematicalProgramInterface::~MathematicalProgramInterface() { }

namespace {

class MathematicalProgram : public MathematicalProgramInterface {
 public:
  virtual ~MathematicalProgram() { }

/* these would be used to fill out the optimization hierarchy prototyped
   below
   virtual MathematicalProgramInterface* addIntegerVariable() { return new
   MathematicalProgram; }

   virtual MathematicalProgramInterface* addLinearCost() { return new
   MathematicalProgram; }
   virtual MathematicalProgramInterface* addQuadraticCost() { return new
   MathematicalProgram; }
   virtual MathematicalProgramInterface* addCost() { return new
   MathematicalProgram; }

   virtual MathematicalProgramInterface* addSumsOfSquaresConstraint() { return new
   MathematicalProgram; }
   virtual MathematicalProgramInterface* addLinearMatrixInequalityConstraint() {
   return new MathematicalProgram; }
   virtual MathematicalProgramInterface* addSecondOrderConeConstraint() { return new
   MathematicalProgram; }
   virtual MathematicalProgramInterface* addComplementarityConstraint() { return new
   MathematicalProgram; };
*/
  virtual MathematicalProgramInterface* addGenericObjective() override {
    return new MathematicalProgram;
  };
  virtual MathematicalProgramInterface* addGenericConstraint() override {
    return new MathematicalProgram;
  };
  virtual MathematicalProgramInterface* addLinearConstraint() override {
    return new MathematicalProgram;
  };
  virtual MathematicalProgramInterface* addLinearEqualityConstraint() override {
    return new MathematicalProgram;
  };
  virtual bool solve(OptimizationProblem& prog) const override {
    throw std::runtime_error("not implemented yet");
  }
};

class NonlinearProgram : public MathematicalProgram {
 public:
    virtual MathematicalProgramInterface* addGenericObjective() override {
      return new NonlinearProgram;
    };
    virtual MathematicalProgramInterface* addGenericConstraint() override {
      return new NonlinearProgram;
    };
    virtual MathematicalProgramInterface* addLinearConstraint() override {
      return new NonlinearProgram;
    };
    virtual MathematicalProgramInterface* addLinearEqualityConstraint() override {
      return new NonlinearProgram;
    };

  virtual bool solve(OptimizationProblem& prog) const override {
    if (snopt_solver.available()) { return snopt_solver.solve(prog); }
    return MathematicalProgram::solve(prog);
  }

 private:
  MathematicalProgramSNOPTSolver snopt_solver;
};

/*  // Prototype of the more complete optimization problem class hiearchy (to
    be implemented only as needed)
    struct MixedIntegerNonlinearProgram : public MathematicalProgramInterface {};
    struct MixedIntegerSemidefiniteProgram : public
    MixedIntegerNonlinearProgram {};
    struct MixedIntegerSecondOrderConeProgram : public
    MixedIntegerSemidefiniteProgram {};
    struct MixedIntegerQuadraticProgram : public
    MixedIntegerSecondOrderConeProgram {};
    struct MixedIntegerLinearProgram : public MixedIntegerQuadraticProgram {};

    struct NonlinearProgram : public MixedIntegerNonlinearProgram {};
    struct SemidefiniteProgram : public NonlinearProgram, public
    MixedIntegerSemidefiniteProgram {};
    struct SecondOrderConeProgram : public SemidefiniteProgram, public
    MixedIntegerSecondOrderConeProgram {};
    struct QuadraticProgram : public SecondOrderConeProgram, public
    MixedIntegerQuadraticProgram {};
    struct LinearProgram : public QuadraticProgram, public
    MixedIntegerLinearProgram {
    virtual MathematicalProgramInterface* addLinearEqualityConstraint() { return new
    LinearProgram; };
    virtual MathematicalProgramInterface* addLinearInequalityConstraint() { return
    new LinearProgram; };
    };

    struct NonlinearComplementarityProblem : public NonlinearProgram {};
    struct LinearComplementarityProblem : public
    NonlinearComplementarityProblem {};
*/

class LeastSquares
    : public NonlinearProgram {  // public LinearProgram, public
 public:
  // LinearComplementarityProblem
  virtual MathematicalProgramInterface* addLinearEqualityConstraint() override {
    return new LeastSquares;
  };
  virtual bool solve(OptimizationProblem& prog) const override {
    size_t num_constraints = 0;
    for (auto const& binding : prog.getLinearEqualityConstraints()) {
      num_constraints += binding.getConstraint()->getMatrix().rows();
    }

    Eigen::MatrixXd Aeq = Eigen::MatrixXd::Zero(
        num_constraints, prog.getNumVars());  // todo: use a sparse matrix here?
    Eigen::VectorXd beq(num_constraints);

    size_t constraint_index = 0;
    for (auto const& binding :  prog.getLinearEqualityConstraints()) {
      auto const& c = binding.getConstraint();
      size_t n = c->getMatrix().rows();
      size_t var_index = 0;
      for (const DecisionVariableView& v : binding.getVariableList()) {
        Aeq.block(constraint_index, v.index(), n, v.size()) =
            c->getMatrix().middleCols(var_index, v.size());
        var_index += v.size();
      }
      beq.segment(constraint_index, n) =
          c->getLowerBound();  // = c->getUpperBound() since it's an equality
      // constraint
      constraint_index += n;
    }

    std::cout << "LeastSquares::solve():\n"
          << "  - aeq =\n" << Aeq << "\n"
          << "  - beq =\n" << beq << "\n"
          << "  - Aeq.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).singularValues()=\n"
          << Aeq.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).singularValues()
          << std::endl;

    // least-squares solution
    prog.setDecisionVariableValues(
        Aeq.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(beq));
    return true;
  }
};
}

std::shared_ptr<MathematicalProgramInterface>
MathematicalProgramInterface::getLeastSquaresProgram() {
  return std::shared_ptr<MathematicalProgramInterface>(new LeastSquares);
}

MathematicalProgramSolverInterface::~MathematicalProgramSolverInterface() { }

}
<|endoftext|>


<commit_before>#pragma once

#include "../../testing/testing.hpp"
#include "../glconstants.hpp"
#include "../../base/logging.hpp"

namespace dp
{
  struct MemoryComparer
  {
    void * m_mem;
    int m_size;

    MemoryComparer(void * memory, int size)
      : m_mem(memory)
      , m_size(size)
    {
    }

    void cmpSubBuffer(glConst /*type*/, uint32_t size, void const * data, uint32_t /*offset*/) const
    {
      TEST_EQUAL(size, m_size, ());
      TEST_EQUAL(memcmp(m_mem, data, size), 0, ());
    }

    void cmpSubImage(uint32_t /*x*/, uint32_t /*y*/, uint32_t /*width*/, uint32_t /*height*/,
                     glConst /*layout*/, glConst /*pixelFormat*/, void const * data) const
    {
      TEST_EQUAL(memcmp(m_mem, data, m_size), 0, ());
    }
  };

}
<commit_msg>[linux] Compile fix<commit_after>#pragma once

#include "../../testing/testing.hpp"
#include "../glconstants.hpp"
#include "../../base/logging.hpp"

#include "../../std/cstring.hpp"

namespace dp
{
  struct MemoryComparer
  {
    void * m_mem;
    int m_size;

    MemoryComparer(void * memory, int size)
      : m_mem(memory)
      , m_size(size)
    {
    }

    void cmpSubBuffer(glConst /*type*/, uint32_t size, void const * data, uint32_t /*offset*/) const
    {
      TEST_EQUAL(size, m_size, ());
      TEST_EQUAL(memcmp(m_mem, data, size), 0, ());
    }

    void cmpSubImage(uint32_t /*x*/, uint32_t /*y*/, uint32_t /*width*/, uint32_t /*height*/,
                     glConst /*layout*/, glConst /*pixelFormat*/, void const * data) const
    {
      TEST_EQUAL(memcmp(m_mem, data, m_size), 0, ());
    }
  };

}
<|endoftext|>


<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/
#include <osg/ClampColor>
#include <osg/GLExtensions>
#include <osg/State>
#include <osg/Notify>
#include <osg/buffered_value>

using namespace osg;

ClampColor::ClampColor():
   _clampVertexColor(GL_FIXED_ONLY),
   _clampFragmentColor(GL_FIXED_ONLY),
   _clampReadColor(GL_FIXED_ONLY)
{
}

ClampColor::ClampColor(GLenum vertexMode, GLenum fragmentMode, GLenum readMode):
   _clampVertexColor(vertexMode),
   _clampFragmentColor(fragmentMode),
   _clampReadColor(readMode)
{
}

ClampColor::~ClampColor()
{
}

void ClampColor::apply(State& state) const
{

   // get the contextID (user defined ID of 0 upwards) for the
    // current OpenGL context.
    const GLExtensions* extensions = state.get<GLExtensions>();
    if (!extensions->isClampColorSupported)
    {
        OSG_WARN<<"Warning: ClampColor::apply(..) failed, ClampColor is not support by OpenGL driver."<<std::endl;
        return;
    }

    extensions->glClampColor(GL_CLAMP_VERTEX_COLOR, _clampVertexColor);
    extensions->glClampColor(GL_CLAMP_FRAGMENT_COLOR, _clampFragmentColor);
    extensions->glClampColor(GL_CLAMP_READ_COLOR, _clampReadColor);
}
<commit_msg>GL_CLAMP_VERTEX_COLOR and GL_CLAMP_FRAGMENT_COLOR deprecated in GL core profile according to OpenGL 4.5 specification.<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/
#include <osg/ClampColor>
#include <osg/GLExtensions>
#include <osg/State>
#include <osg/Notify>
#include <osg/buffered_value>

using namespace osg;

ClampColor::ClampColor():
   _clampVertexColor(GL_FIXED_ONLY),
   _clampFragmentColor(GL_FIXED_ONLY),
   _clampReadColor(GL_FIXED_ONLY)
{
}

ClampColor::ClampColor(GLenum vertexMode, GLenum fragmentMode, GLenum readMode):
   _clampVertexColor(vertexMode),
   _clampFragmentColor(fragmentMode),
   _clampReadColor(readMode)
{
}

ClampColor::~ClampColor()
{
}

void ClampColor::apply(State& state) const
{

   // get the contextID (user defined ID of 0 upwards) for the
    // current OpenGL context.
    const GLExtensions* extensions = state.get<GLExtensions>();
    if (!extensions->isClampColorSupported)
    {
        OSG_WARN<<"Warning: ClampColor::apply(..) failed, ClampColor is not support by OpenGL driver."<<std::endl;
        return;
    }

#if !defined(OSG_GL3_AVAILABLE)
    extensions->glClampColor(GL_CLAMP_VERTEX_COLOR, _clampVertexColor);
    extensions->glClampColor(GL_CLAMP_FRAGMENT_COLOR, _clampFragmentColor);
#endif
    extensions->glClampColor(GL_CLAMP_READ_COLOR, _clampReadColor);
}
<|endoftext|>