text:
// Copyright (c) 2014, Alexey Ivanov

#include "stdafx.h"
#include "image.h"
#include <boost/noncopyable.hpp>
#include "utils/util.h"

namespace ImageUtils
{
namespace FreeImage
{

/* Adapter for std::vector<BYTE> to save/load into it by FreeImage library. */
class FIIOVectorHandle : boost::noncopyable
{
public:
    typedef std::vector<BYTE> ImageDataType;

    FIIOVectorHandle(ImageDataType& image_data)
        :
        cur_position_(0), image_data_(image_data)
    {}

    /* Allow implicit cast to fi_handle. */
    operator fi_handle()
    {
        return this;
    }

    static unsigned DLL_CALLCONV ReadProc(void* buffer, unsigned size, unsigned count, fi_handle handle)
    {
        FIIOVectorHandle* handle_ = static_cast<FIIOVectorHandle*>(handle);
        unsigned x;
        for (x = 0; x < count; ++x) {
            //if there isnt size bytes left to read, set pos to eof and return a short count
            if( handle_->image_data_.size() - handle_->cur_position_ < size ) {
                handle_->cur_position_ = handle_->image_data_.size();
                break;
            }
            //copy size bytes count times
            memcpy(buffer, &(handle_->image_data_[0]) + handle_->cur_position_, size);
            handle_->cur_position_ += size;
            buffer = static_cast<char*>(buffer) + size;
        }
        return x;
    }

    static unsigned DLL_CALLCONV WriteProc(void* buffer, unsigned size, unsigned count, fi_handle handle)
    {
        typedef FIIOVectorHandle::ImageDataType::size_type SizeType;
        FIIOVectorHandle* handle_ = static_cast<FIIOVectorHandle*>(handle);

        //double the data block size if we need to
        SizeType required_image_data_size = handle_->cur_position_ + (size * count);
        if ( required_image_data_size >= handle_->image_data_.capacity() ) {

            SizeType current_image_data_size = handle_->image_data_.size(); // cash current image data size
            SizeType new_capacity;
            //if we are at or above 1G, we cant double without going negative
            if (current_image_data_size & 0x40000000) {
                //max 2G
                if (current_image_data_size == 0x7FFFFFFF) {
                    return 0;
                }
                new_capacity = 0x7FFFFFFF;
            } else if (current_image_data_size == 0) {
                //default to 4K if nothing yet
                new_capacity = 4096;
            } else {
                //double size
                new_capacity = required_image_data_size << 1;
            }

            handle_->image_data_.reserve(new_capacity);
        }

        handle_->image_data_.insert( handle_->image_data_.end(),
                                     static_cast<BYTE*>(buffer),
                                     static_cast<BYTE*>(buffer) + size * count);
        handle_->cur_position_ += (size * count);
        return count;
    }

    static int DLL_CALLCONV SeekProc(fi_handle handle, long offset, int origin)
    {
        FIIOVectorHandle* handle_ = static_cast<FIIOVectorHandle*>(handle);
        switch (origin) // 0 to filelen-1 are 'inside' the file
        {
        default:
        case SEEK_SET: // can fseek() to 0-7FFFFFFF always
            if (offset >= 0) {
                handle_->cur_position_ = offset;
                return 0;
            }
            break;

        case SEEK_CUR:
        {
            INT64 new_position = static_cast<INT64>(handle_->cur_position_) + offset;
            if ( 0 <= new_position && new_position <= handle_->image_data_.size() ) {
                handle_->cur_position_ += offset;
                return 0;
            }
            break;
        }

        case SEEK_END:
            if (offset <= 0) {
                INT64 new_position = static_cast<INT64>(handle_->image_data_.size()) + offset;
                if (new_position >= 0) {
                    handle_->cur_position_ = static_cast<FIIOVectorHandle::ImageDataType::size_type>(new_position);
                    return 0;
                }
            }
            break;
        }

        return -1;
    }

    static long DLL_CALLCONV TellProc(fi_handle handle)
    {
        return static_cast<FIIOVectorHandle*>(handle)->cur_position_;
    }

    /* Initialize FreeImageIO struct. */
    void InitFreeImageIO(FreeImageIO* io)
    {
        io->read_proc  = FIIOVectorHandle::ReadProc;
        io->seek_proc  = FIIOVectorHandle::SeekProc;
        io->tell_proc  = FIIOVectorHandle::TellProc;
        io->write_proc = FIIOVectorHandle::WriteProc;
    }

private:

    ImageDataType::size_type cur_position_;
    ImageDataType& image_data_;
};

//// use for store data about error in FreeImage library.
//std::string free_library_last_error_message;

/* Function used to get error description from FreeImage library, see FreeImage_SetOutputMessage description.
    Depends on FreeImage.lib and commented.
*/
//void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message) {
//    std::ostringstream msg;
//    if (fif != FIF_UNKNOWN) {
//        msg << FreeImage_GetFormatFromFIF(fif) << " format. ";
//    }
//    msg << message;
//    free_library_last_error_message = msg.str();
//}

} // namespace FreeImage

//! Get size of bitmap by it's handle.
SIZE getBitmapSize(HBITMAP bitmap_handle)
{
    BITMAP bitmap;
    int errorcode = GetObject(bitmap_handle, sizeof(bitmap), &bitmap);
    if (0 == errorcode) {
        throw std::runtime_error("Failed to get size of bitmap.");
    }

    SIZE bitmap_size = { bitmap.bmWidth, bitmap.bmHeight };
    return bitmap_size;
}

//! general tempate for convinient casting. Provide specialization for your own types.
template<typename To, typename From> To cast(From);

/*!
    \brief Converts image format ID from AIMPCoverImage to FREE_IMAGE_FORMAT.
    If AIMPCoverImage format is unknown returns FIF_UNKNOWN format.
*/
template<>
FREE_IMAGE_FORMAT cast<FREE_IMAGE_FORMAT, IMAGEFORMAT>(IMAGEFORMAT image_format)
{
    FREE_IMAGE_FORMAT freeimage_format = FIF_UNKNOWN;
    switch (image_format)
    {
    case PNG_IMAGE:
        freeimage_format = FIF_PNG;
        break;
    case BMP_IMAGE:
        freeimage_format = FIF_BMP;
        break;
    case JPEG_IMAGE:
        freeimage_format = FIF_JPEG;
        break;
    }
    return freeimage_format;
}

AIMPCoverImage::AIMPCoverImage(HBITMAP cover_bitmap_handle, unsigned width, unsigned height) // throws std::runtime_error
    :
    cover_bitmap_handle_(cover_bitmap_handle)
{
    BOOL result = copyFromBitmap(cover_bitmap_handle);
    if (FALSE == result) {
        throw std::runtime_error("Error occured while create AIMPCoverImage from HBITMAP.");
    }

    if (width != 0 && height != 0) {
        SIZE size = { width, height };
        SIZE bitmap_size = getBitmapSize(cover_bitmap_handle_);
        if (bitmap_size.cx != size.cx || bitmap_size.cy != size.cy) {
            result = rescale(size.cx, size.cy, FREE_IMAGE_FILTER::FILTER_BICUBIC);
            if (FALSE == result) {
                using namespace Utilities;
                throw std::runtime_error(MakeString() << "Error occured while rescaling image to (" << size.cx << ", " << size.cy << ").");
            }
        }
    }

    result = convertTo24Bits();
    if (FALSE == result) {
        throw std::runtime_error("Error occured while converting AIMPCoverImage to 24bpp.");
    }
}

void AIMPCoverImage::saveToVector(IMAGEFORMAT image_format, std::vector<BYTE>& image_data) const // throws std::runtime_error
{
    using namespace FreeImage;

    FIIOVectorHandle memory_handle(image_data);
    FreeImageIO io;
    memory_handle.InitFreeImageIO(&io);

    //FreeImage_SetOutputMessage(FreeImage::FreeImageErrorHandler); // set handler that fill FreeImage::free_library_last_error_message string in case of error.
    BOOL result = saveToHandle(cast<FREE_IMAGE_FORMAT>(image_format), &io, &memory_handle);
    //FreeImage_SetOutputMessage(nullptr); // remove error handler.
    if (FALSE == result) {
        using namespace Utilities;
        throw std::runtime_error(MakeString() << "Error occured while saving image in vector. Reason: " << "unknown"); // << FreeImage::free_library_last_error_message;
    }
}

void AIMPCoverImage::saveToFile(const std::wstring& file_name) const // throws std::runtime_error
{
    //FreeImage_SetOutputMessage(FreeImage::FreeImageErrorHandler); // set handler that fill FreeImage::free_library_last_error_message string in case of error.
    BOOL result = saveU(file_name.c_str(), 0); // 0 means default saving settings.
    //using namespace FreeImage;
    //free_library_last_error_message = free_library_last_error_message;
    //FreeImage_SetOutputMessage(nullptr); // remove error handler.

    if (FALSE == result) {
        using namespace Utilities;
        throw std::runtime_error(MakeString() << "Error occured while saving image to file. Reason: " << "unknown"); // << FreeImage::free_library_last_error_message;
    }
}

} // namespace ImageUtils


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

#include <boost/algorithm/string.hpp>

#include "codegen/llvm-codegen.h"
#include "runtime/descriptors.h"
#include "runtime/mem-pool.h"
#include "runtime/runtime-state.h"
#include "runtime/string-value.h"
#include "runtime/timestamp-value.h"
#include "runtime/tuple.h"
#include "text-converter.h"
#include "util/string-parser.h"

using namespace boost;
using namespace impala;
using namespace llvm;
using namespace std;

<<<<<<< HEAD
TextConverter::TextConverter(char escape_char)
  : escape_char_(escape_char) {
=======
TextConverter::TextConverter(char escape_char, const string& null_col_val,
    bool check_null)
  : escape_char_(escape_char),
    null_col_val_(null_col_val),
    check_null_(check_null) {
>>>>>>> d520a9cdea2fc97e8d5da9fbb0244e60ee416bfa
}

void TextConverter::UnescapeString(StringValue* value, MemPool* pool) {
  char* new_data = reinterpret_cast<char*>(pool->Allocate(value->len));
  UnescapeString(value->ptr, new_data, &value->len);
  value->ptr = new_data;
}

<<<<<<< HEAD
void TextConverter::UnescapeString(const char* src, char* dest, int* len) {
  char* dest_ptr = dest;
  const char* end = src + *len;
  bool escape_next_char = false;
  while (src < end) {
=======
void TextConverter::UnescapeString(const char* src, char* dest, int* len,
    int64_t maxlen) {
  const char* src_end = src + *len;
  char* dest_end = dest + *len;
  if (maxlen > 0) dest_end = dest + maxlen;
  char* dest_ptr = dest;
  bool escape_next_char = false;

  while ((src < src_end) && (dest_ptr < dest_end)) {
>>>>>>> d520a9cdea2fc97e8d5da9fbb0244e60ee416bfa
    if (*src == escape_char_) {
      escape_next_char = !escape_next_char;
    } else {
      escape_next_char = false;
    }
    if (escape_next_char) {
      ++src;
    } else {
      *dest_ptr++ = *src++;
    }
  }
  char* dest_start = reinterpret_cast<char*>(dest);
  *len = dest_ptr - dest_start;
}

// Codegen for a function to parse one slot.  The IR for a int slot looks like:
// define i1 @WriteSlot({ i8, i32 }* %tuple_arg, i8* %data, i32 %len) {
// entry:
//   %parse_result = alloca i32
//   %0 = call i1 @IsNullString(i8* %data, i32 %len)
//   br i1 %0, label %set_null, label %check_zero
<<<<<<< HEAD
//
// set_null:                                         ; preds = %check_zero, %entry
//   call void @SetNull({ i8, i32 }* %tuple_arg)
//   ret i1 true
//
=======
//
// set_null:                                         ; preds = %check_zero, %entry
//   call void @SetNull({ i8, i32 }* %tuple_arg)
//   ret i1 true
//
>>>>>>> d520a9cdea2fc97e8d5da9fbb0244e60ee416bfa
// parse_slot:                                       ; preds = %check_zero
//   %slot = getelementptr inbounds { i8, i32 }* %tuple_arg, i32 0, i32 1
//   %1 = call i32 @IrStringToInt32(i8* %data, i32 %len, i32* %parse_result)
//   %parse_result1 = load i32* %parse_result
//   %failed = icmp eq i32 %parse_result1, 1
//   br i1 %failed, label %parse_fail, label %parse_success
<<<<<<< HEAD
//
// check_zero:                                       ; preds = %entry
//   %2 = icmp eq i32 %len, 0
//   br i1 %2, label %set_null, label %parse_slot
//
// parse_success:                                    ; preds = %parse_slot
//   store i32 %1, i32* %slot
//   ret i1 true
//
=======
//
// check_zero:                                       ; preds = %entry
//   %2 = icmp eq i32 %len, 0
//   br i1 %2, label %set_null, label %parse_slot
//
// parse_success:                                    ; preds = %parse_slot
//   store i32 %1, i32* %slot
//   ret i1 true
//
>>>>>>> d520a9cdea2fc97e8d5da9fbb0244e60ee416bfa
// parse_fail:                                       ; preds = %parse_slot
//   call void @SetNull({ i8, i32 }* %tuple_arg)
//   ret i1 false
// }
<<<<<<< HEAD
Function* TextConverter::CodegenWriteSlot(LlvmCodeGen* codegen,
    TupleDescriptor* tuple_desc, SlotDescriptor* slot_desc) {
  SCOPED_TIMER(codegen->codegen_timer());

  // Codegen is_null_string
  Function* is_null_string_fn = codegen->GetFunction(IRFunction::STRING_IS_NULL);
=======
Function* TextConverter::CodegenWriteSlot(LlvmCodeGen* codegen,
    TupleDescriptor* tuple_desc, SlotDescriptor* slot_desc,
    const char* null_col_val, int len, bool check_null) {
  if (slot_desc->type().type == TYPE_CHAR) {
    LOG(INFO) << "Char isn't supported for CodegenWriteSlot";
    return NULL;
  }
  SCOPED_TIMER(codegen->codegen_timer());

  // Codegen is_null_string
  bool is_default_null = (len == 2 && null_col_val[0] == '\\' && null_col_val[1] == 'N');
  Function* is_null_string_fn;
  if (is_default_null) {
    is_null_string_fn = codegen->GetFunction(IRFunction::IS_NULL_STRING);
  } else {
    is_null_string_fn = codegen->GetFunction(IRFunction::GENERIC_IS_NULL_STRING);
  }
>>>>>>> d520a9cdea2fc97e8d5da9fbb0244e60ee416bfa
  if (is_null_string_fn == NULL) return NULL;

  StructType* tuple_type = tuple_desc->GenerateLlvmStruct(codegen);
  if (tuple_type == NULL) return NULL;
  PointerType* tuple_ptr_type = PointerType::get(tuple_type, 0);

  Function* set_null_fn = slot_desc->CodegenUpdateNull(codegen, tuple_type, true);
  if (set_null_fn == NULL) {
    LOG(ERROR) << "Could not codegen WriteSlot because slot update codegen failed.";
    return NULL;
  }

  LlvmCodeGen::FnPrototype prototype(
      codegen, "WriteSlot", codegen->GetType(TYPE_BOOLEAN));
  prototype.AddArgument(LlvmCodeGen::NamedVariable("tuple_arg", tuple_ptr_type));
  prototype.AddArgument(LlvmCodeGen::NamedVariable("data", codegen->ptr_type()));
  prototype.AddArgument(LlvmCodeGen::NamedVariable("len", codegen->GetType(TYPE_INT)));

  LlvmCodeGen::LlvmBuilder builder(codegen->context());
  Value* args[3];
  Function* fn = prototype.GeneratePrototype(&builder, &args[0]);

  BasicBlock* set_null_block, *parse_slot_block, *check_zero_block = NULL;
<<<<<<< HEAD
  codegen->CreateIfElseBlocks(fn, "set_null", "parse_slot",
      &set_null_block, &parse_slot_block);

  if (slot_desc->type() != TYPE_STRING) {
    check_zero_block = BasicBlock::Create(codegen->context(), "check_zero", fn);
  }

  // Check if the data is '\N'
  Value* is_null = builder.CreateCall2(is_null_string_fn, args[1], args[2]);
  builder.CreateCondBr(is_null, set_null_block,
      slot_desc->type() == TYPE_STRING ? parse_slot_block : check_zero_block);

  if (slot_desc->type() != TYPE_STRING) {
    builder.SetInsertPoint(check_zero_block);
    // If len == 0 and it is not a string col, set slot to NULL
    Value* len_zero = builder.CreateICmpEQ(args[2], codegen->GetIntConstant(TYPE_INT, 0));
    builder.CreateCondBr(len_zero, set_null_block, parse_slot_block);
  }
=======
  codegen->CreateIfElseBlocks(fn, "set_null", "parse_slot",
      &set_null_block, &parse_slot_block);

  if (!slot_desc->type().IsVarLen()) {
    check_zero_block = BasicBlock::Create(codegen->context(), "check_zero", fn);
  }

  // Check if the data matches the configured NULL string.
  Value* is_null;
  if (check_null) {
    if (is_default_null) {
      is_null = builder.CreateCall2(is_null_string_fn, args[1], args[2]);
    } else {
      is_null = builder.CreateCall4(is_null_string_fn, args[1], args[2],
          codegen->CastPtrToLlvmPtr(codegen->ptr_type(),
              const_cast<char*>(null_col_val)),
          codegen->GetIntConstant(TYPE_INT, len));
    }
  } else {
    // Constant FALSE as branch condition. We rely on later optimization passes
    // to remove the branch and THEN block.
    is_null = codegen->false_value();
  }
  builder.CreateCondBr(is_null, set_null_block,
      (slot_desc->type().IsVarLen()) ? parse_slot_block : check_zero_block);

  if (!slot_desc->type().IsVarLen()) {
    builder.SetInsertPoint(check_zero_block);
    // If len <= 0 and it is not a string col, set slot to NULL
    // The len can be less than 0 if the field contained an escape character which
    // is only valid for string cols.
    Value* null_len = builder.CreateICmpSLE(
        args[2], codegen->GetIntConstant(TYPE_INT, 0));
    builder.CreateCondBr(null_len, set_null_block, parse_slot_block);
  }
>>>>>>> d520a9cdea2fc97e8d5da9fbb0244e60ee416bfa

  // Codegen parse slot block
  builder.SetInsertPoint(parse_slot_block);
  Value* slot = builder.CreateStructGEP(args[0], slot_desc->field_idx(), "slot");

<<<<<<< HEAD
  if (slot_desc->type() == TYPE_STRING) {
    Value* ptr = builder.CreateStructGEP(slot, 0, "string_ptr");
    Value* len = builder.CreateStructGEP(slot, 1, "string_len");
    builder.CreateStore(args[1], ptr);
    builder.CreateStore(args[2], len);
=======
  if (slot_desc->type().IsVarLen()) {
    Value* ptr = builder.CreateStructGEP(slot, 0, "string_ptr");
    Value* len = builder.CreateStructGEP(slot, 1, "string_len");

    builder.CreateStore(args[1], ptr);
    // TODO codegen memory allocation for CHAR
    DCHECK(slot_desc->type().type != TYPE_CHAR);
    if (slot_desc->type().type == TYPE_VARCHAR) {
      // determine if we need to truncate the string
      Value* maxlen = codegen->GetIntConstant(TYPE_INT, slot_desc->type().len);
      Value* len_lt_maxlen = builder.CreateICmpSLT(args[2], maxlen, "len_lt_maxlen");
      Value* minlen = builder.CreateSelect(len_lt_maxlen, args[2], maxlen,
                                           "select_min_len");
      builder.CreateStore(minlen, len);
    } else {
      builder.CreateStore(args[2], len);
    }
>>>>>>> d520a9cdea2fc97e8d5da9fbb0244e60ee416bfa
    builder.CreateRet(codegen->true_value());
  } else {
    IRFunction::Type parse_fn_enum;
    Function* parse_fn = NULL;
<<<<<<< HEAD
    switch (slot_desc->type()) {
=======
    switch (slot_desc->type().type) {
>>>>>>> d520a9cdea2fc97e8d5da9fbb0244e60ee416bfa
      case TYPE_BOOLEAN:
        parse_fn_enum = IRFunction::STRING_TO_BOOL;
        break;
      case TYPE_TINYINT:
        parse_fn_enum = IRFunction::STRING_TO_INT8;
        break;
<<<<<<< HEAD
      case TYPE_SMALLINT:
        parse_fn_enum = IRFunction::STRING_TO_INT16;
        break;
      case TYPE_INT:
=======
      case TYPE_SMALLINT:
        parse_fn_enum = IRFunction::STRING_TO_INT16;
        break;
      case TYPE_INT:
>>>>>>> d520a9cdea2fc97e8d5da9fbb0244e60ee416bfa
        parse_fn_enum = IRFunction::STRING_TO_INT32;
        break;
      case TYPE_BIGINT:
        parse_fn_enum = IRFunction::STRING_TO_INT64;
        break;
      case TYPE_FLOAT:
        parse_fn_enum = IRFunction::STRING_TO_FLOAT;
        break;
      case TYPE_DOUBLE:
        parse_fn_enum = IRFunction::STRING_TO_DOUBLE;
        break;
      default:
        DCHECK(false);
        return NULL;
    }
    parse_fn = codegen->GetFunction(parse_fn_enum);
    DCHECK(parse_fn != NULL);

    // Set up trying to parse the string to the slot type
    BasicBlock* parse_success_block, *parse_failed_block;
    codegen->CreateIfElseBlocks(fn, "parse_success", "parse_fail",
        &parse_success_block, &parse_failed_block);
    LlvmCodeGen::NamedVariable parse_result("parse_result", codegen->GetType(TYPE_INT));
    Value* parse_result_ptr = codegen->CreateEntryBlockAlloca(fn, parse_result);
    Value* failed_value = codegen->GetIntConstant(TYPE_INT, StringParser::PARSE_FAILURE);

    // Call Impala's StringTo* function
    Value* result = builder.CreateCall3(parse_fn, args[1], args[2], parse_result_ptr);
    Value* parse_result_val = builder.CreateLoad(parse_result_ptr, "parse_result");

    // Check for parse error.  TODO: handle overflow
    Value* parse_failed = builder.CreateICmpEQ(parse_result_val, failed_value, "failed");
    builder.CreateCondBr(parse_failed, parse_failed_block, parse_success_block);
<<<<<<< HEAD

=======

>>>>>>> d520a9cdea2fc97e8d5da9fbb0244e60ee416bfa
    // Parse succeeded
    builder.SetInsertPoint(parse_success_block);
    builder.CreateStore(result, slot);
    builder.CreateRet(codegen->true_value());

    // Parse failed, set slot to null and return false
    builder.SetInsertPoint(parse_failed_block);
    builder.CreateCall(set_null_fn, args[0]);
    builder.CreateRet(codegen->false_value());
  }

  // Case where data is \N or len == 0 and it is not a string col
  builder.SetInsertPoint(set_null_block);
  builder.CreateCall(set_null_fn, args[0]);
  builder.CreateRet(codegen->true_value());

  return codegen->FinalizeFunction(fn);
}

ext: cc

max_stars_repo_name: zhennan-sun/impala

max_issues_repo_name: zhennan-sun/impala

max_forks_repo_name: zhennan-sun/impala


text:
/*
 * gpcxx/tree/detail/node_helpers.hpp
 * Date: 2013-09-14
 * Author: Karsten Ahnert (karsten.ahnert@gmx.de)
 * Copyright: Karsten Ahnert
 *
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or
 * copy at http://www.boost.org/LICENSE_1_0.txt)
 */

#ifndef GPCXX_TREE_DETAIL_NODE_HELPERS_HPP_INCLUDED
#define GPCXX_TREE_DETAIL_NODE_HELPERS_HPP_INCLUDED

#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>

#include <type_traits>

namespace gpcxx {
namespace detail {

template< typename Node >
struct node_value_getter : public boost::mpl::eval_if<
    std::is_const< Node > ,
    std::add_const< typename Node::value_type > ,
    boost::mpl::identity< typename Node::value_type >
  >
{
};

template< typename Node >
struct node_base_getter : public boost::mpl::eval_if<
    std::is_const< Node > ,
    std::add_const< typename Node::node_base_type > ,
    boost::mpl::identity< typename Node::node_base_type >
    >
{
};

} // namespace detail
} // namespace gpcxx

#endif // GPCXX_TREE_DETAIL_NODE_HELPERS_HPP_INCLUDED

ext: hpp

max_stars_repo_name: gchoinka/gpcxx

max_issues_repo_name: gchoinka/gpcxx

max_forks_repo_name: gchoinka/gpcxx


text:
/*
 * (C) Copyright 2015 Kurento (http://kurento.org/)
 *
 * 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.
 *
 */

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE UriEndpoint
#include <boost/test/unit_test.hpp>
#include <MediaPipelineImpl.hpp>
#include <MediaElementImpl.hpp>
#include <ElementConnectionData.hpp>
#include <MediaType.hpp>
#include <KurentoException.hpp>
#include <objects/UriEndpointImpl.hpp>
#include <MediaSet.hpp>
#include <ModuleManager.hpp>

using namespace kurento;

std::string mediaPipelineId;
ModuleManager moduleManager;
boost::property_tree::ptree config;

struct GF {
  GF();
  ~GF();
};

class UriEndpointFactory : public Factory
{
public:
  std::string getName () const override { return "UriEndpointFactory"; }

protected:
  MediaObjectImpl *createObjectPointer (const boost::property_tree::ptree &conf,
      const Json::Value &params) const override
  {
    std::string mediaPipelineId = params["mediaPipeline"].asString ();
    std::string uri = params["uri"].asString ();

    std::shared_ptr <MediaObjectImpl> pipe =
      MediaSet::getMediaSet ()->getMediaObject (mediaPipelineId);

    return new  UriEndpointImpl (config, pipe, "dummyuri", uri);
  }
};

BOOST_GLOBAL_FIXTURE (GF);

GF::GF()
{
  gst_init(nullptr, nullptr);
  moduleManager.loadModulesFromDirectories ("../../src/server");
}

GF::~GF()
{
  MediaSet::deleteMediaSet();
}

static void
releaseMediaObject (const std::string &id)
{
  MediaSet::getMediaSet ()->release (id);
}

static std::shared_ptr <UriEndpointImpl> generateUriEndpoint (
  const std::string &mediaPipelineId, const std::string &uri)
{
  UriEndpointFactory factory;
  Json::Value params;

  params["mediaPipeline"] = mediaPipelineId;
  params["uri"] = uri;

  return std::dynamic_pointer_cast<UriEndpointImpl> (
           factory.createObject (config, "", params) );
}

BOOST_AUTO_TEST_CASE (check_regular_uri)
{
  std::string uri;
  std::string first_uri = "file:///tmp/file.webm";

  mediaPipelineId =
    moduleManager.getFactory ("MediaPipeline")->createObject (
      config, "",
      Json::Value() )->getId();

  config.add ("modules.kurento.UriEndpoint.configPath", "../../../tests" );
  config.add ("modules.kurento.UriEndpoint.defaultPath", "file:///var/kurento/");

  std::shared_ptr <UriEndpointImpl> uriEndpoint = generateUriEndpoint (
        mediaPipelineId, first_uri);

  uri = uriEndpoint->getUri ();

  if (uri != first_uri) {
    BOOST_ERROR ("Wrong URI returned by UriEndpoint");
  }

  releaseMediaObject (uriEndpoint->getId() );
  releaseMediaObject (mediaPipelineId);

  uriEndpoint.reset ();
}

BOOST_AUTO_TEST_CASE (check_media_element_uri)
{
  std::string uri;
  std::string first_uri = "file.webm";
  std::string expected_uri = "file:///var/kurento/file.webm";
  char *uri_value;

  mediaPipelineId =
    moduleManager.getFactory ("MediaPipeline")->createObject (
      config, "",
      Json::Value() )->getId();

  config.add ("modules.kurento.UriEndpoint.configPath", "../../../tests" );
  config.add ("modules.kurento.UriEndpoint.defaultPath", "file:///var/kurento/");

  std::shared_ptr <UriEndpointImpl> uriEndpoint = generateUriEndpoint (
        mediaPipelineId, first_uri);

  uri = uriEndpoint->getUri ();

  if (uri != first_uri) {
    BOOST_ERROR ("Wrong URI returned by UriEndpoint");
  }

  g_object_get (G_OBJECT (uriEndpoint->getGstreamerElement() ), "uri", &uri_value,
                NULL);

  if (g_strcmp0 (uri_value, expected_uri.c_str () ) != 0) {
    BOOST_ERROR ("Wrong URI returned by gstreamer element");
  }

  g_free (uri_value);

  releaseMediaObject (uriEndpoint->getId() );
  releaseMediaObject (mediaPipelineId);

  uriEndpoint.reset ();
}

BOOST_AUTO_TEST_CASE (check_uri_with_escaped_slashes)
{
  std::string uri;
  std::string first_uri =
    "https://test.com/026cba3020160826100051.mp4?params=host&user=AKIAIHFQODXEKWDTKIRQ%2F20160826%2Ftest%2Fs3%2Floc4_request&pass=db575aaf678085c2595df3bc3bc614";

  mediaPipelineId =
    moduleManager.getFactory ("MediaPipeline")->createObject (
      config, "",
      Json::Value() )->getId();

  config.add ("modules.kurento.UriEndpoint.configPath", "../../../tests" );
  config.add ("modules.kurento.UriEndpoint.defaultPath", "file:///var/kurento/");

  std::shared_ptr <UriEndpointImpl> uriEndpoint = generateUriEndpoint (
        mediaPipelineId, first_uri);

  releaseMediaObject (uriEndpoint->getId() );
  releaseMediaObject (mediaPipelineId);

  uriEndpoint.reset ();
}

ext: cpp

max_stars_repo_name: slabajo/kms-core

max_issues_repo_name: slabajo/kms-core

max_forks_repo_name: slabajo/kms-core


text:
#include "Debug.h"
#include "Configs.hpp"
#include <cassert>
#include <iostream>
#include <boost/stacktrace.hpp>

namespace gen
{

void Debug::ASSERT(const bool expression)
{
    if constexpr (Config::DEBUG)
    {
        if (!expression)
        {
            std::cerr << boost::stacktrace::stacktrace() << std::endl;
            std::abort();
        }
    }
}

void Debug::ASSERT(const bool expression, std::string_view svMessage)
{
    if constexpr (Config::DEBUG)
    {
        if (!expression)
        {
            std::cerr << boost::stacktrace::stacktrace() << std::endl;
            std::cerr << svMessage << std::endl;
            std::abort();
        }
    }
}

} // namespace gen

max_stars_repo_name: ArgishtyAyvazyan/DedalCompiler

max_issues_repo_name: ArgishtyAyvazyan/DedalCompiler

max_forks_repo_name: ArgishtyAyvazyan/DedalCompiler


text:
/*!
@file
Defines `boost::hana::IntegralConstant` and includes `Logical` and
`Comparable`.

@copyright Louis Dionne 2015
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
 */

#ifndef BOOST_HANA_BOOL_HPP
#define BOOST_HANA_BOOL_HPP

#include <boost/hana/fwd/bool.hpp>

#include <boost/hana/constant.hpp>
#include <boost/hana/core/convert.hpp>
#include <boost/hana/core/datatype.hpp>
#include <boost/hana/core/models.hpp>
#include <boost/hana/core/operators.hpp>
#include <boost/hana/detail/std/forward.hpp>
#include <boost/hana/detail/std/integer_sequence.hpp>
#include <boost/hana/detail/std/is_integral.hpp>
#include <boost/hana/detail/std/size_t.hpp>

// provided models; the rest is included in <boost/hana/integral_constant.hpp>
#include <boost/hana/logical.hpp>
#include <boost/hana/comparable.hpp>

// operators
#include <boost/hana/fwd/group.hpp>
#include <boost/hana/fwd/integral_domain.hpp>
#include <boost/hana/fwd/monoid.hpp>
#include <boost/hana/fwd/orderable.hpp>
#include <boost/hana/fwd/ring.hpp>

namespace boost { namespace hana {
    //////////////////////////////////////////////////////////////////////////
    // integral_constant
    //////////////////////////////////////////////////////////////////////////
    //! @cond
    namespace ic_detail {
        template <typename T, T N, typename = detail::std::make_integer_sequence<T, N>>
        struct go;

        template <typename T, T N, T ...i>
        struct go<T, N, detail::std::integer_sequence<T, i...>> {
            using swallow = T[];

            template <typename F>
            static constexpr void with_index(F&& f)
            { (void)swallow{T{}, ((void)f(integral_constant<T, i>), i)...}; }

            template <typename F>
            static constexpr void without_index(F&& f)
            { (void)swallow{T{}, ((void)f(), i)...}; }
        };

        template <typename T, T v>
        template <typename F>
        constexpr void _with_index<T, v>::operator()(F&& f) const
        { go<T, (sizeof(F), v)>::with_index(detail::std::forward<F>(f)); }

        template <typename T, T v>
        template <typename F>
        constexpr void _times<T, v>::operator()(F&& f) const
        { go<T, (sizeof(F), v)>::without_index(detail::std::forward<F>(f)); }

        // avoid link-time error
        template <typename T, T v>
        constexpr _with_index<T, v> _times<T, v>::with_index;
    }

    // avoid link-time error
    template <typename T, T v>
    constexpr ic_detail::_times<T, v> _integral_constant<T, v>::times;

    template <typename T, T v>
    struct datatype<_integral_constant<T, v>> {
        using type = IntegralConstant<T>;
    };
    //! @endcond

    //////////////////////////////////////////////////////////////////////////
    // Operators (most of them are provided by the concepts)
    //////////////////////////////////////////////////////////////////////////
    template <typename T>
    struct operators::of<IntegralConstant<T>>
        : operators::of<
              Comparable, Orderable
            , Logical
            , Monoid, Group, Ring, IntegralDomain
        >
    { };

#define BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(op)                          \
    template <typename U, U u, typename V, V v>                             \
    constexpr _integral_constant<decltype(u op v), (u op v)>                \
    operator op(_integral_constant<U, u>, _integral_constant<V, v>)         \
    { return {}; }                                                          \
    /**/

#define BOOST_HANA_INTEGRAL_CONSTANT_UNARY_OP(op)                           \
    template <typename U, U u>                                              \
    constexpr _integral_constant<decltype(op u), (op u)>                    \
    operator op(_integral_constant<U, u>)                                   \
    { return {}; }                                                          \
    /**/

    // Arithmetic
    BOOST_HANA_INTEGRAL_CONSTANT_UNARY_OP(+)

    // Bitwise
    BOOST_HANA_INTEGRAL_CONSTANT_UNARY_OP(~)
    BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(&)
    BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(|)
    BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(^)
    BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(<<)
    BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(>>)

#undef BOOST_HANA_INTEGRAL_CONSTANT_UNARY_OP
#undef BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP

    //////////////////////////////////////////////////////////////////////////
    // User-defined literal
    //////////////////////////////////////////////////////////////////////////
    namespace ic_detail {
        constexpr int to_int(char c)
        { return static_cast<int>(c) - 48; }

        template <detail::std::size_t N>
        constexpr long long parse(const char (&arr)[N]) {
            long long number = 0, base = 1;
            for (detail::std::size_t i = 0; i < N; ++i) {
                number += to_int(arr[N - 1 - i]) * base;
                base *= 10;
            }
            return number;
        }
    }

    namespace literals {
        template <char ...c>
        constexpr auto operator"" _c()
        { return llong<ic_detail::parse<sizeof...(c)>({c...})>; }
    }

    //////////////////////////////////////////////////////////////////////////
    // Model of Constant
    //////////////////////////////////////////////////////////////////////////
    template <typename T>
    struct value_impl<IntegralConstant<T>> {
        template <typename C>
        static constexpr auto apply()
        { return C::value; }
    };

    template <typename T, typename C>
    struct to_impl<IntegralConstant<T>, C, when<
        _models<Constant, C>{} &&
        detail::std::is_integral<typename C::value_type>{}
    >>
        : embedding<is_embedded<typename C::value_type, T>{}>
    {
        static_assert(detail::std::is_integral<T>{},
        "trying to convert a Constant to an IntegralConstant of a non-integral "
        "type; boost::hana::IntegralConstant may only hold integral types");

        template <typename X>
        static constexpr auto apply(X const&) {
            constexpr T v = hana::value<X>();
            return integral_constant<T, v>;
        }
    };
}} // end namespace boost::hana

#endif // !BOOST_HANA_BOOL_HPP

max_stars_repo_name: josephwinston/hana

max_issues_repo_name: josephwinston/hana

max_forks_repo_name: josephwinston/hana


text:
// Copyright (C) 2009-2012 Lorenzo Caminiti
// Distributed under the Boost Software License, Version 1.0
// (see accompanying file LICENSE_1_0.txt or a copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Home at http://www.boost.org/libs/local_function

#include <boost/config.hpp>
#ifdef BOOST_NO_CXX11_VARIADIC_MACROS
#   error "variadic macros required"
#else

#include <boost/local_function.hpp>
#include <boost/detail/lightweight_test.hpp>

int main(void) {
    //[nesting
    int x = 0;

    void BOOST_LOCAL_FUNCTION(bind& x) {
        void BOOST_LOCAL_FUNCTION(bind& x) { // Nested.
            x++;
        } BOOST_LOCAL_FUNCTION_NAME(g)

        x--;
        g(); // Nested local function call.
    } BOOST_LOCAL_FUNCTION_NAME(f)

    f();
    //]

    BOOST_TEST(x == 0);
    return boost::report_errors();
}

#endif // VARIADIC_MACROS


text:
// ======================================================================
// \title  FrameTransformImpl.hpp
// \author gene
// \brief  hpp file for FrameTransform component implementation class
//
// \copyright
// Copyright 2009-2015, by the California Institute of Technology.
// ALL RIGHTS RESERVED.  United States Government Sponsorship
// acknowledged. Any commercial use must be negotiated with the Office
// of Technology Transfer at the California Institute of Technology.
//
// This software may be subject to U.S. export control laws and
// regulations.  By accepting this document, the user agrees to comply
// with all U.S. export laws and regulations.  User has the
// responsibility to obtain export licenses, or other export authority
// as may be required before exporting such information to foreign
// countries or providing access to foreign persons.
// ======================================================================

#ifndef FrameTransform_HPP
#define FrameTransform_HPP

#include "Gnc/Utils/FrameTransform/FrameTransformComponentAc.hpp"

#include <Eigen/Geometry>

namespace Gnc {

  class FrameTransformComponentImpl :
    public FrameTransformComponentBase
  {

    public:

      // ----------------------------------------------------------------------
      // Construction, initialization, and destruction
      // ----------------------------------------------------------------------

      //! Construct object FrameTransform
      //!
      FrameTransformComponentImpl(
#if FW_OBJECT_NAMES == 1
          const char *const compName /*!< The component name*/
#else
          void
#endif
      );

      //! Initialize object FrameTransform
      //!
      void init(
          const NATIVE_INT_TYPE instance = 0 /*!< The instance number*/
      );

      //! Destroy object FrameTransform
      //!
      ~FrameTransformComponentImpl(void);

      EIGEN_MAKE_ALIGNED_OPERATOR_NEW

    PRIVATE:
      void parameterUpdated(FwPrmIdType id /*!< The parameter ID*/);

      void parametersLoaded();

      // ----------------------------------------------------------------------
      // Handler implementations for user-defined typed input ports
      // ----------------------------------------------------------------------

      //! Handler implementation for prmTrigger
      //!
      void prmTrigger_handler(
          const NATIVE_INT_TYPE portNum, /*!< The port number*/
          FwPrmIdType dummy
      );

      //! Handler implementation for odomInA
      //!
      void odomInA_handler(
          const NATIVE_INT_TYPE portNum, /*!< The port number*/
          ROS::nav_msgs::OdometryAccel &Odometry
      );

      //! Handler implementation for odomInB
      //!
      void odomInB_handler(
          const NATIVE_INT_TYPE portNum, /*!< The port number*/
          ROS::nav_msgs::OdometryAccel &Odometry
      );

    PRIVATE:

      // ----------------------------------------------------------------------
      // Command handler implementations
      // ----------------------------------------------------------------------

      //! Implementation for FTFO_InitParams command handler
      //!
      void FTFO_InitParams_cmdHandler(
          const FwOpcodeType opCode, /*!< The opcode*/
          const U32 cmdSeq /*!< The command sequence number*/
      );

      bool paramsInited;

      Eigen::Affine3d a_X_b; // takes point in b frame to a frame
      Eigen::Affine3d b_X_a; // takes point in a frame to b frame

      bool doRotX; // see params.xml
      bool doRotV; // see params.xml

    };

} // end namespace Gnc

#endif

max_stars_repo_name: genemerewether/fprime

max_issues_repo_name: genemerewether/fprime

max_forks_repo_name: genemerewether/fprime


text:
/**
 * Copyright (c) 2017 Melown Technologies SE
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * *  Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * *  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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
 */
#ifndef http_detail_detail_hpp_included_
#define http_detail_detail_hpp_included_

#include <memory>
#include <set>
#include <string>
#include <atomic>
#include <thread>
#include <condition_variable>

#include <boost/noncopyable.hpp>
#include <boost/asio.hpp>
#include <boost/optional.hpp>

#include "utility/buildsys.hpp"
#include "utility/eventcounter.hpp"

#include "../http.hpp"
#include "../contentfetcher.hpp"
#include "dnscache.hpp"
#include "curl.hpp"

namespace http {

namespace asio = boost::asio;
namespace ip = asio::ip;
namespace bs = boost::system;
namespace ubs = utility::buildsys;
typedef asio::ip::tcp tcp;

namespace detail {
class ServerConnection;
struct Request;
class Acceptor;
} // namespace detail

class Http::Detail
    : boost::noncopyable
    , public ContentFetcher
{
public:
    Detail();

    ~Detail() { stop(); }

    void request(const std::shared_ptr<detail::ServerConnection> &connection
                 , const detail::Request &request);

    void addServerConnection
    (const std::shared_ptr<detail::ServerConnection> &conn);
    void removeServerConnection
    (const std::shared_ptr<detail::ServerConnection> &conn);

    /** Starts server threads.
     */
    void startServer(std::size_t count);

    /** Starts client threads.
     */
    void startClient(std::size_t count,
                     const ContentFetcher::Options *options = nullptr);

    /** Strop all threads.
     */
    void stop();

    utility::TcpEndpoint
    listen(const utility::TcpEndpoint &listen
           , const ContentGenerator::pointer &contentGenerator);

    static Detail& detail(const Http &http) { return *http.detail_; }

    asio::io_service& ioService() { return ios_; }

    void serverHeader(const std::string &value) {
        serverHeader_ = value;
    }

    const std::string& serverHeader() const { return serverHeader_; }

    void request() { requestCounter_.event(); }

    void stat(std::ostream &os) const;

private:
    virtual void fetch_impl(const std::string &location
                            , const ClientSink::pointer &sink
                            , const RequestOptions &options);

    void worker(std::size_t id);

    asio::io_service ios_;
    boost::optional<asio::io_service::work> work_;
    detail::DnsCache dnsCache_;
    std::vector<std::thread> workers_;

    std::vector<std::shared_ptr<detail::Acceptor>> acceptors_;
    std::set<std::shared_ptr<detail::ServerConnection>> connections_;
    std::mutex connMutex_;
    std::condition_variable connCond_;
    std::atomic<bool> running_;
    std::string serverHeader_;
    utility::EventCounter connectionCounter_;
    utility::EventCounter requestCounter_;

    std::mutex clientMutex_;

    /** CURL based clients.
     */
    detail::CurlClient::list clients_;

    /** Current client. Workload is distributed in round-robin manner.
     */
    detail::CurlClient::list::iterator currentClient_;
};

} // namespace http

#endif // http_detail_detail_hpp_included_

max_stars_repo_name: HanochZhu/vts-browser-unity-plugin

max_issues_repo_name: HanochZhu/vts-browser-unity-plugin

max_forks_repo_name: HanochZhu/vts-browser-unity-plugin


text:
// All content Copyright (C) 2018 Genomics plc
#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>
#include <string>
#include <bits/shared_ptr.h>

#include "variant/genotype.hpp"
#include "variant/haplotype.hpp"
#include "variant/type/variant.hpp"
#include "caller/diploid/diploidAnnotate.hpp"

using wecall::variant::GenotypeVector;
using wecall::variant::HaplotypeVector;
using wecall::variant::genotypePtr_t;
using wecall::variant::varPtr_t;
using wecall::variant::variantSet_t;
using wecall::variant::Haplotype;
using wecall::utils::ReferenceSequence;
using wecall::caller::Region;
using wecall::variant::Variant;

BOOST_AUTO_TEST_CASE( testConstructsAllPloidy2CombinationsFromHaplotypeVector )
{
    const auto referenceSequence = std::make_shared< ReferenceSequence >( Region( "1", 0, 1 ), "A" );

    varPtr_t snp1 = std::make_shared< Variant >( referenceSequence, Region( "1", 0, 1 ), "C" );
    varPtr_t snp2 = std::make_shared< Variant >( referenceSequence, Region( "1", 0, 1 ), "G" );
    varPtr_t snp3 = std::make_shared< Variant >( referenceSequence, Region( "1", 0, 1 ), "T" );
    HaplotypeVector haplotypeVector( Region( "1", 0, 1 ), referenceSequence );
    haplotypeVector.push_back( variantSet_t{} );
    haplotypeVector.push_back( variantSet_t{snp1} );
    haplotypeVector.push_back( variantSet_t{snp2} );
    haplotypeVector.push_back( variantSet_t{snp3} );

    const auto ploidy = 2;

    const GenotypeVector genotypeVector( ploidy, haplotypeVector, {0, 1, 2, 3}, {} );

    BOOST_REQUIRE_EQUAL( genotypeVector.size(), 10 );  // multinomialElements(4, 2)
    BOOST_CHECK_EQUAL( genotypeVector.ploidy(), ploidy );

    // Check genotype uniqueness
    std::set< std::vector< std::size_t > > haplotypeIndicesSet;
    for ( std::size_t i = 0; i < genotypeVector.size(); ++i )
    {
        const auto haplotypeIndices = genotypeVector.getHaplotypeIndices( i );
        BOOST_REQUIRE_EQUAL( haplotypeIndices.size(), ploidy );

        haplotypeIndicesSet.insert( haplotypeIndices );
    }
    BOOST_CHECK_EQUAL( haplotypeIndicesSet.size(), 10 );
}

BOOST_AUTO_TEST_CASE( testPloidy2GenotypeCombinations )
{
    const auto referenceSequence = std::make_shared< ReferenceSequence >( Region( "1", 0, 1 ), "A" );

    varPtr_t snp = std::make_shared< Variant >( referenceSequence, Region( "1", 0, 1 ), "C" );
    HaplotypeVector haplotypeVector( Region( "1", 0, 1 ), referenceSequence );
    haplotypeVector.push_back( variantSet_t{} );
    haplotypeVector.push_back( variantSet_t{snp} );

    const auto ploidy = 2;

    const GenotypeVector genotypeVector( ploidy, haplotypeVector, {0, 1}, {} );

    BOOST_REQUIRE_EQUAL( genotypeVector.size(), 3 );

    BOOST_CHECK_EQUAL( genotypeVector[0]->nCombinationsThisGenotype(), 1 );
    BOOST_CHECK_EQUAL( genotypeVector[1]->nCombinationsThisGenotype(), 2 );
    BOOST_CHECK_EQUAL( genotypeVector[2]->nCombinationsThisGenotype(), 1 );
}

BOOST_AUTO_TEST_CASE( testPloidy2GenotypeVectorOrdering )
{
    const auto referenceSequence = std::make_shared< ReferenceSequence >( Region( "1", 0, 2 ), "AA" );

    const auto snp0 = std::make_shared< Variant >( referenceSequence, Region( "1", 0, 1 ), "C" );
    const auto snp1 = std::make_shared< Variant >( referenceSequence, Region( "1", 1, 2 ), "C" );

    HaplotypeVector haplotypeVector( Region( "1", 0, 2 ), referenceSequence );
    auto regionReference = haplotypeVector.regionReferenceSequence();
    haplotypeVector.push_back( variantSet_t{} );            //  hap0
    haplotypeVector.push_back( variantSet_t{snp0} );        //  hap1
    haplotypeVector.push_back( variantSet_t{snp0, snp1} );  //  hap2

    const auto ploidy = 2;

    const GenotypeVector genotypeVector( ploidy, haplotypeVector, {0, 1, 2}, {} );

    BOOST_REQUIRE_EQUAL( genotypeVector.size(), 6 );

    // Ref-ref
    BOOST_REQUIRE_EQUAL( genotypeVector[0]->nStrandsContainingVariant( haplotypeVector, snp0 ), 0 );
    BOOST_REQUIRE_EQUAL( genotypeVector[0]->nStrandsContainingVariant( haplotypeVector, snp1 ), 0 );

    // Ref-hap1
    BOOST_REQUIRE_EQUAL( genotypeVector[1]->nStrandsContainingVariant( haplotypeVector, snp0 ), 1 );
    BOOST_REQUIRE_EQUAL( genotypeVector[1]->nStrandsContainingVariant( haplotypeVector, snp1 ), 0 );

    // Ref-hap2
    BOOST_REQUIRE_EQUAL( genotypeVector[2]->nStrandsContainingVariant( haplotypeVector, snp0 ), 1 );
    BOOST_REQUIRE_EQUAL( genotypeVector[2]->nStrandsContainingVariant( haplotypeVector, snp1 ), 1 );

    // hap1-hap1
    BOOST_REQUIRE_EQUAL( genotypeVector[3]->nStrandsContainingVariant( haplotypeVector, snp0 ), 2 );
    BOOST_REQUIRE_EQUAL( genotypeVector[3]->nStrandsContainingVariant( haplotypeVector, snp1 ), 0 );

    // hap1-hap2
    BOOST_REQUIRE_EQUAL( genotypeVector[4]->nStrandsContainingVariant( haplotypeVector, snp0 ), 2 );
    BOOST_REQUIRE_EQUAL( genotypeVector[4]->nStrandsContainingVariant( haplotypeVector, snp1 ), 1 );

    // hap2-hap2
    BOOST_REQUIRE_EQUAL( genotypeVector[5]->nStrandsContainingVariant( haplotypeVector, snp0 ), 2 );
    BOOST_REQUIRE_EQUAL( genotypeVector[5]->nStrandsContainingVariant( haplotypeVector, snp1 ), 2 );
}

max_stars_repo_name: dylex/wecall

max_issues_repo_name: dylex/wecall

max_forks_repo_name: dylex/wecall


text:
/*!
@file
Forward declares `boost::hana::optional`.

@copyright Louis Dionne 2013-2016
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
 */

#ifndef BOOST_HANA_FWD_OPTIONAL_HPP
#define BOOST_HANA_FWD_OPTIONAL_HPP

#include <boost/hana/config.hpp>
#include <boost/hana/detail/operators/adl.hpp>
#include <boost/hana/fwd/core/make.hpp>

BOOST_HANA_NAMESPACE_BEGIN
    //! @ingroup group-datatypes
    //! Optional value whose optional-ness is known at compile-time.
    //!
    //! An `optional` either contains a value (represented as `just(x)`), or
    //! it is empty (represented as `nothing`). In essence, `hana::optional`
    //! is pretty much like a `boost::optional` or the upcoming `std::optional`,
    //! except for the fact that whether a `hana::optional` is empty or not is
    //! known at compile-time. This can be particularly useful for returning
    //! from a function that might fail, but whose reason for failing is not
    //! important. Of course, whether the function will fail has to be known
    //! at compile-time.
    //!
    //! This is really an important difference between `hana::optional` and
    //! `std::optional`. Unlike `std::optional<T>{}` and `std::optional<T>{x}`
    //! who share the same type (`std::optional<T>`), `hana::just(x)` and
    //! `hana::nothing` do not share the same type, since the state of the
    //! optional has to be known at compile-time. Hence, whether a `hana::just`
    //! or a `hana::nothing` will be returned from a function has to be known
    //! at compile-time for the return type of that function to be computable
    //! by the compiler. This makes `hana::optional` well suited for static
    //! metaprogramming tasks, but very poor for anything dynamic.
    //!
    //!
    //! Interoperation with `type`s
    //! ---------------------------
    //! When a `just` contains an object of type `T` which is a `type`,
    //! it has a nested `::%type` alias equivalent to `T::%type`. `nothing`,
    //! however, never has a nested `::%type` alias. If `t` is a `type`,
    //! this allows `decltype(just(t))` to be seen as a nullary metafunction
    //! equivalent to `decltype(t)`. Along with the `sfinae` function,
    //! this allows `hana::optional` to interact seamlessly with
    //! SFINAE-friendly metafunctions.
    //! Example:
    //! @include example/optional/sfinae_friendly_metafunctions.cpp
    //!
    //!
    //! Modeled concepts
    //! ----------------
    //! 1. `Comparable`\n
    //! Two `optional`s are equal if and only if they are both empty or they
    //! both contain a value and those values are equal.
    //! @include example/optional/comparable.cpp
    //!
    //! 2. `Orderable`\n
    //! Optional values can be ordered by considering the value they are
    //! holding, if any. To handle the case of an empty optional value, we
    //! arbitrarily set `nothing` as being less than any other `just`. Hence,
    //! @code
    //!     just(x) < just(y) if and only if x < y
    //!     nothing < just(anything)
    //! @endcode
    //! Example:
    //! @include example/optional/orderable.cpp
    //!
    //! 3. `Functor`\n
    //! An optional value can be seen as a list containing either one element
    //! (`just(x)`) or no elements at all (`nothing`). As such, mapping
    //! a function over an optional value is equivalent to applying it to
    //! its value if there is one, and to `nothing` otherwise:
    //! @code
    //!     transform(just(x), f) == just(f(x))
    //!     transform(nothing, f) == nothing
    //! @endcode
    //! Example:
    //! @include example/optional/functor.cpp
    //!
    //! 4. `Applicative`\n
    //! First, a value can be made optional with `lift<optional_tag>`, which
    //! is equivalent to `just`. Second, one can feed an optional value to an
    //! optional function with `ap`, which will return `just(f(x))` if there
    //! is both a function _and_ a value, and `nothing` otherwise:
    //! @code
    //!     ap(just(f), just(x)) == just(f(x))
    //!     ap(nothing, just(x)) == nothing
    //!     ap(just(f), nothing) == nothing
    //!     ap(nothing, nothing) == nothing
    //! @endcode
    //! A simple example:
    //! @include example/optional/applicative.cpp
    //! A more complex example:
    //! @include example/optional/applicative.complex.cpp
    //!
    //! 5. `Monad`\n
    //! The `Monad` model makes it easy to compose actions that might fail.
    //! One can feed an optional value if there is one into a function with
    //! `chain`, which will return `nothing` if there is no value. Finally,
    //! optional-optional values can have their redundant level of optionality
    //! removed with `flatten`. Also note that the `|` operator can be used in
    //! place of the `chain` function.
    //! Example:
    //! @include example/optional/monad.cpp
    //!
    //! 6. `MonadPlus`\n
    //! The `MonadPlus` model allows choosing the first valid value out of
    //! two optional values with `concat`. If both optional values are
    //! `nothing`s, `concat` will return `nothing`.
    //! Example:
    //! @include example/optional/monad_plus.cpp
    //!
    //! 7. `Foldable`\n
    //! Folding an optional value is equivalent to folding a list containing
    //! either no elements (for `nothing`) or `x` (for `just(x)`).
    //! Example:
    //! @include example/optional/foldable.cpp
    //!
    //! 8. `Searchable`\n
    //! Searching an optional value is equivalent to searching a list
    //! containing `x` for `just(x)` and an empty list for `nothing`.
    //! Example:
    //! @include example/optional/searchable.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
    template <typename ...T>
    struct optional {
        // 5.3.1, Constructors

        //! Default-construct an `optional`. Only exists if the optional
        //! contains a value, and if that value is DefaultConstructible.
        constexpr optional() = default;

        //! Copy-construct an `optional`.
        //! An empty optional may only be copy-constructed from another
        //! empty `optional`, and an `optional` with a value may only be
        //! copy-constructed from another `optional` with a value.
        //! Furthermore, this constructor only exists if the value
        //! held in the `optional` is CopyConstructible.
        optional(optional const&) = default;

        //! Move-construct an `optional`.
        //! An empty optional may only be move-constructed from another
        //! empty `optional`, and an `optional` with a value may only be
        //! move-constructed from another `optional` with a value.
        //! Furthermore, this constructor only exists if the value
        //! held in the `optional` is MoveConstructible.
        optional(optional&&) = default;

        //! Construct an `optional` holding a value of type `T` from another
        //! object of type `T`. The value is copy-constructed.
        constexpr optional(T const& t)
            : value_(t)
        { }

        //! Construct an `optional` holding a value of type `T` from another
        //! object of type `T`. The value is move-constructed.
        constexpr optional(T&& t)
            : value_(static_cast<T&&>(t))
        { }

        // 5.3.3, Assignment

        //! Copy-assign an `optional`.
        //! An empty optional may only be copy-assigned from another empty
        //! `optional`, and an `optional` with a value may only be copy-assigned
        //! from another `optional` with a value. Furthermore, this assignment
        //! operator only exists if the value held in the `optional` is
        //! CopyAssignable.
        constexpr optional& operator=(optional const&) = default;

        //! Move-assign an `optional`.
        //! An empty optional may only be move-assigned from another empty
        //! `optional`, and an `optional` with a value may only be move-assigned
        //! from another `optional` with a value. Furthermore, this assignment
        //! operator only exists if the value held in the `optional` is
        //! MoveAssignable.
        constexpr optional& operator=(optional&&) = default;

        // 5.3.5, Observers

        //! Returns a pointer to the contained value, or a `nullptr` if the
        //! `optional` is empty.
        //!
        //!
        //! @note Overloads of this method are provided for both the `const`
        //! and the non-`const` cases.
        //!
        //!
        //! Example
        //! -------
        //! @include example/optional/value.cpp
        constexpr T* operator->();

        //! Extract the content of an `optional`, or fail at compile-time.
        //!
        //! If `*this` contains a value, that value is returned. Otherwise,
        //! a static assertion is triggered.
        //!
        //! @note
        //! Overloads of this method are provided for the cases where `*this`
        //! is a reference, a rvalue-reference and their `const` counterparts.
        //!
        //!
        //! Example
        //! -------
        //! @include example/optional/value.cpp
        constexpr T& value();

        //! Equivalent to `value()`, provided for convenience.
        //!
        //! @note
        //! Overloads of this method are provided for the cases where `*this`
        //! is a reference, a rvalue-reference and their `const` counterparts.
        //!
        //!
        //! Example
        //! -------
        //! @include example/optional/value.cpp
        constexpr T& operator*();

        //! Return the contents of an `optional`, with a fallback result.
        //!
        //! If `*this` contains a value, that value is returned. Otherwise,
        //! the default value provided is returned.
        //!
        //! @note
        //! Overloads of this method are provided for the cases where `*this`
        //! is a reference, a rvalue-reference and their `const` counterparts.
        //!
        //!
        //! @param default_
        //! The default value to return if `*this` does not contain a value.
        //!
        //!
        //! Example
        //! -------
        //! @include example/optional/value_or.cpp
        template <typename U>
        constexpr decltype(auto) value_or(U&& default_);

        //! Equivalent to `hana::chain`.
        template <typename ...T, typename F>
        friend constexpr auto operator|(optional<T...>, F);

        //! Equivalent to `hana::equal`
        template <typename X, typename Y>
        friend constexpr auto operator==(X&& x, Y&& y);

        //! Equivalent to `hana::not_equal`
        template <typename X, typename Y>
        friend constexpr auto operator!=(X&& x, Y&& y);

        //! Equivalent to `hana::less`
        template <typename X, typename Y>
        friend constexpr auto operator<(X&& x, Y&& y);

        //! Equivalent to `hana::greater`
        template <typename X, typename Y>
        friend constexpr auto operator>(X&& x, Y&& y);

        //! Equivalent to `hana::less_equal`
        template <typename X, typename Y>
        friend constexpr auto operator<=(X&& x, Y&& y);

        //! Equivalent to `hana::greater_equal`
        template <typename X, typename Y>
        friend constexpr auto operator>=(X&& x, Y&& y);
    };
#else
    template <typename ...T>
    struct optional;
#endif

    //! Tag representing a `hana::optional`.
    //! @relates hana::optional
    struct optional_tag { };

    //! Create an optional value.
    //! @relates hana::optional
    //!
    //! Specifically, `make<optional_tag>()` is equivalent to `nothing`, and
    //! `make<optional_tag>(x)` is equivalent to `just(x)`. This is provided
    //! for consistency with the other `make<...>` functions.
    //!
    //!
    //! Example
    //! -------
    //! @include example/optional/make.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
    template <>
    constexpr auto make<optional_tag> = []([auto&& x]) {
        return optional<std::decay<decltype(x)>::type>{forwarded(x)};
    };
#endif

    //! Alias to `make<optional_tag>`; provided for convenience.
    //! @relates hana::optional
    //!
    //!
    //! Example
    //! -------
    //! @include example/optional/make.cpp
    constexpr auto make_optional = make<optional_tag>;

    //! Create an optional value containing `x`.
    //! @relates hana::optional
    //!
    //!
    //! Example
    //! -------
    //! @include example/optional/just.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
    constexpr auto just = [](auto&& x) {
        return optional<std::decay<decltype(x)>::type>{forwarded(x)};
    };
#else
    struct make_just_t {
        template <typename T>
        constexpr auto operator()(T&&) const;
    };

    constexpr make_just_t just{};
#endif

    //! An empty optional value.
    //! @relates hana::optional
    //!
    //!
    //! Example
    //! -------
    //! @include example/optional/nothing.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
    constexpr optional<> nothing{};
#else
    template <>
    struct optional<> : detail::operators::adl<optional<>> {
        // 5.3.1, Constructors
        constexpr optional() = default;
        constexpr optional(optional const&) = default;
        constexpr optional(optional&&) = default;

        // 5.3.3, Assignment
        constexpr optional& operator=(optional const&) = default;
        constexpr optional& operator=(optional&&) = default;

        // 5.3.5, Observers
        constexpr decltype(nullptr) operator->() const { return nullptr; }

        template <typename ...dummy>
        constexpr auto value() const;

        template <typename ...dummy>
        constexpr auto operator*() const;

        template <typename U>
        constexpr U&& value_or(U&& u) const;
    };

    constexpr optional<> nothing{};
#endif

    //! Apply a function to the contents of an optional, with a fallback
    //! result.
    //! @relates hana::optional
    //!
    //! Specifically, `maybe` takes a default value, a function and an
    //! optional value. If the optional value is `nothing`, the default
    //! value is returned. Otherwise, the function is applied to the
    //! content of the `just`.
    //!
    //!
    //! @param default_
    //! A default value returned if `m` is `nothing`.
    //!
    //! @param f
    //! A function called as `f(x)` if and only if `m` is an optional value
    //! of the form `just(x)`. In that case, the result returend by `maybe`
    //! is the result of `f`.
    //!
    //! @param m
    //! An optional value.
    //!
    //!
    //! Example
    //! -------
    //! @include example/optional/maybe.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
    constexpr auto maybe = [](auto&& default_, auto&& f, auto&& m) -> decltype(auto) {
        if (m is a just(x)) {
            return forwarded(f)(forwarded(x));
        else
            return forwarded(default_);
        }
    };
#else
    struct maybe_t {
        template <typename Def, typename F, typename T>
        constexpr decltype(auto) operator()(Def&&, F&& f, optional<T> const& m) const
        { return static_cast<F&&>(f)(m.value_); }

        template <typename Def, typename F, typename T>
        constexpr decltype(auto) operator()(Def&&, F&& f, optional<T>& m) const
        { return static_cast<F&&>(f)(m.value_); }

        template <typename Def, typename F, typename T>
        constexpr decltype(auto) operator()(Def&&, F&& f, optional<T>&& m) const
        { return static_cast<F&&>(f)(static_cast<optional<T>&&>(m).value_); }

        template <typename Def, typename F>
        constexpr Def operator()(Def&& def, F&&, optional<> const&) const
        { return static_cast<Def&&>(def); }
    };

    constexpr maybe_t maybe{};
#endif

    //! Calls a function if the call expression is well-formed.
    //! @relates hana::optional
    //!
    //! Given a function `f`, `sfinae` returns a new function applying `f`
    //! to its arguments and returning `just` the result if the call is
    //! well-formed, and `nothing` otherwise. In other words, `sfinae(f)(x...)`
    //! is `just(f(x...))` if that expression is well-formed, and `nothing`
    //! otherwise. Note, however, that it is possible for an expression
    //! `f(x...)` to be well-formed as far as SFINAE is concerned, but
    //! trying to actually compile `f(x...)` still fails. In this case,
    //! `sfinae` won't be able to detect it and a hard failure is likely
    //! to happen.
    //!
    //!
    //! @note
    //! The function given to `sfinae` must not return `void`, since
    //! `just(void)` does not make sense. A compilation error is
    //! triggered if the function returns void.
    //!
    //!
    //! Example
    //! -------
    //! @include example/optional/sfinae.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
    auto sfinae = [](auto&& f) {
        return [perfect-capture](auto&& ...x) {
            if (decltype(forwarded(f)(forwarded(x)...)) is well-formed)
                return just(forwarded(f)(forwarded(x)...));
            else
                return nothing;
        };
    };
#else
    struct sfinae_t {
        template <typename F>
        constexpr decltype(auto) operator()(F&& f) const;
    };

    constexpr sfinae_t sfinae{};
#endif

    //! Return whether an `optional` contains a value.
    //! @relates hana::optional
    //!
    //! Specifically, returns a compile-time true-valued `Logical` if `m` is
    //! of the form `just(x)` for some `x`, and a false-valued one otherwise.
    //!
    //!
    //! Example
    //! -------
    //! @include example/optional/is_just.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
    constexpr auto is_just = [](auto const& m) {
        return m is a just(x);
    };
#else
    struct is_just_t {
        template <typename ...T>
        constexpr auto operator()(optional<T...> const&) const;
    };

    constexpr is_just_t is_just{};
#endif

    //! Return whether an `optional` is empty.
    //! @relates hana::optional
    //!
    //! Specifically, returns a compile-time true-valued `Logical` if `m` is
    //! a `nothing`, and a false-valued one otherwise.
    //!
    //!
    //! Example
    //! -------
    //! @include example/optional/is_nothing.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
    constexpr auto is_nothing = [](auto const& m) {
        return m is a nothing;
    };
#else
    struct is_nothing_t {
        template <typename ...T>
        constexpr auto operator()(optional<T...> const&) const;
    };

    constexpr is_nothing_t is_nothing{};
#endif
BOOST_HANA_NAMESPACE_END

#endif // !BOOST_HANA_FWD_OPTIONAL_HPP

max_stars_repo_name: rudylee/expo

max_issues_repo_name: rudylee/expo

max_forks_repo_name: rudylee/expo


text:
//==============================================================================
// Copyright 2018-2020 Kitware, Inc., Kitware SAS
// Author: Guilbert Pierre (Kitware SAS)
//         Laurenson Nick (Kitware SAS)
//         Cadart Nicolas (Kitware SAS)
// Creation date: 2018-03-27
//
// 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 "LidarSlam/Utilities.h"
#include "LidarSlam/SpinningSensorKeypointExtractor.h"

#include <Eigen/Dense>
#include <Eigen/Geometry>

namespace LidarSlam
{

namespace
{
//-----------------------------------------------------------------------------
struct LineFitting
{
  //! Fitting using PCA
  bool FitPCA(const SpinningSensorKeypointExtractor::PointCloud& cloud,
              const std::vector<int>& indices);

  //! Fitting using very local line and check if this local line is consistent
  //! in a more global neighborhood
  bool FitPCAAndCheckConsistency(const SpinningSensorKeypointExtractor::PointCloud& cloud,
                                 const std::vector<int>& indices);

  //! Compute the squared distance of a point to the fitted line
  inline float SquaredDistanceToPoint(Eigen::Vector3f const& point) const;

  // Direction and position
  Eigen::Vector3f Direction;
  Eigen::Vector3f Position;

  //! Max distance allowed from the farest point to estimated line to be considered as real line
  float MaxDistance = 0.02;  // [m]

  //! Max angle allowed between consecutive segments in the neighborhood to be considered as line
  float MaxAngle = DEG2RAD(40.);  // [rad]
};

//-----------------------------------------------------------------------------
bool LineFitting::FitPCA(const SpinningSensorKeypointExtractor::PointCloud& cloud,
                         const std::vector<int>& indices)
{
  // Compute PCA to determine best line approximation of the points distribution
  // and save points centroid in Position
  Eigen::Vector3f eigVals;
  Eigen::Matrix3f eigVecs;
  Utils::ComputeMeanAndPCA(cloud, indices, this->Position, eigVecs, eigVals);

  // Get Direction as main eigen vector
  this->Direction = eigVecs.col(2);

  // If a point of the neighborhood is too far from the fitted line,
  // we consider the neighborhood as non flat
  bool isLineFittingAccurate = true;
  const float sqMaxDistance = this->MaxDistance * this->MaxDistance;
  for (const auto& pointId: indices)
  {
    if (this->SquaredDistanceToPoint(cloud[pointId].getVector3fMap()) > sqMaxDistance)
    {
      isLineFittingAccurate = false;
      break;
    }
  }
  return isLineFittingAccurate;
}

//-----------------------------------------------------------------------------
bool LineFitting::FitPCAAndCheckConsistency(const SpinningSensorKeypointExtractor::PointCloud& cloud,
                                            const std::vector<int>& indices)
{
  const float maxSinAngle = std::sin(this->MaxAngle);
  bool isLineFittingAccurate = true;

  // First check if the neighborhood is approximately straight
  const Eigen::Vector3f U = (cloud[indices.back()].getVector3fMap() - cloud[indices.front()].getVector3fMap()).normalized();
  for (unsigned int i = 0; i < indices.size() - 1; i++)
  {
    const Eigen::Vector3f V = (cloud[indices[i + 1]].getVector3fMap() - cloud[indices[i]].getVector3fMap()).normalized();
    const float sinAngle = (U.cross(V)).norm();
    if (sinAngle > maxSinAngle)
    {
      isLineFittingAccurate = false;
      break;
    }
  }

  // Then fit with PCA (only if isLineFittingAccurate is true)
  return isLineFittingAccurate && this->FitPCA(cloud, indices);
}

//-----------------------------------------------------------------------------
inline float LineFitting::SquaredDistanceToPoint(Eigen::Vector3f const& point) const
{
  return ((point - this->Position).cross(this->Direction)).squaredNorm();
}
} // end of anonymous namespace

//-----------------------------------------------------------------------------
void SpinningSensorKeypointExtractor::ComputeKeyPoints(const PointCloud::Ptr& pc)
{
  this->Scan = pc;

  // Split whole pointcloud into separate laser ring clouds
  this->ConvertAndSortScanLines();

  // Initialize the features vectors and keypoints
  this->PrepareDataForNextFrame();

  // Invalidate points with bad criteria
  this->InvalidateNotUsablePoints();

  // Compute keypoints scores
  this->ComputeCurvature();

  // Labelize keypoints
  this->SetKeyPointsLabels();
}

//-----------------------------------------------------------------------------
void SpinningSensorKeypointExtractor::ConvertAndSortScanLines()
{
  // Clear previous scan lines
  for (auto& scanLineCloud: this->ScanLines)
  {
    // Use clear() if pointcloud already exists to avoid re-allocating memory.
    // No worry as ScanLines is never shared with outer scope.
    if (scanLineCloud)
      scanLineCloud->clear();
    else
      scanLineCloud.reset(new PointCloud);
  }

  // Separate pointcloud into different scan lines
  for (const Point& point: *this->Scan)
  {
    // Ensure that there are enough available scan lines
    while (point.laser_id >= this->ScanLines.size())
      this->ScanLines.emplace_back(new PointCloud);

    // Add the current point to its corresponding laser scan
    this->ScanLines[point.laser_id]->push_back(point);
  }

  // Save the number of lasers
  this->NbLaserRings = this->ScanLines.size();

  // Estimate azimuthal resolution if not already done
  // or if the previous value found is not plausible
  // (because last scan was badly formed, e.g. lack of points)
  if (this->AzimuthalResolution < 1e-6 || M_PI/4. < this->AzimuthalResolution)
    this->EstimateAzimuthalResolution();
}

//-----------------------------------------------------------------------------
void SpinningSensorKeypointExtractor::PrepareDataForNextFrame()
{
  // Do not use clear(), otherwise weird things could happen
  // if outer program uses these pointers
  for (auto k : KeypointTypes)
  {
    this->Keypoints[k].reset(new PointCloud);
    Utils::CopyPointCloudMetadata(*this->Scan, *this->Keypoints[k]);
  }

  // Initialize the features vectors with the correct length
  this->Angles.resize(this->NbLaserRings);
  this->Saliency.resize(this->NbLaserRings);
  this->DepthGap.resize(this->NbLaserRings);
  this->IntensityGap.resize(this->NbLaserRings);
  this->IsPointValid.resize(this->NbLaserRings);
  this->Label.resize(this->NbLaserRings);

  // Initialize the scan lines features vectors with the correct length
  #pragma omp parallel for num_threads(this->NbThreads) schedule(guided)
  for (int scanLine = 0; scanLine < static_cast<int>(this->NbLaserRings); ++scanLine)
  {
    size_t nbPoint = this->ScanLines[scanLine]->size();
    this->IsPointValid[scanLine].assign(nbPoint, KeypointFlags().set());  // set all flags to 1
    this->Label[scanLine].assign(nbPoint, KeypointFlags().reset());  // set all flags to 0
    this->Angles[scanLine].assign(nbPoint, 0.);
    this->Saliency[scanLine].assign(nbPoint, 0.);
    this->DepthGap[scanLine].assign(nbPoint, 0.);
    this->IntensityGap[scanLine].assign(nbPoint, 0.);
  }
}

//-----------------------------------------------------------------------------
void SpinningSensorKeypointExtractor::InvalidateNotUsablePoints()
{
  // Max angle between Lidar Ray and hyptothetic plane normal
  const float angleBeamNormal = Utils::Deg2Rad(90 - this->MinBeamSurfaceAngle);
  // If the azimuthal angle was estimated and is plausible,
  // it is used to invalidate points representing occluded areas border.
  // Otherwise, we use a default angle (Velodyne 10Hz resolution)
  float azimuthalResolution = this->AzimuthalResolution;
  if (azimuthalResolution < 1e-6 || M_PI / 4 < azimuthalResolution)
  {
    PRINT_WARNING("Unable to estimate the azimuthal resolution angle: using 0.2°");
    azimuthalResolution = Utils::Deg2Rad(0.2);
  }
  // Coeff to multiply to point depth, in order to obtain the maximal distance
  // between two neighbors of the same Lidar ray on a plane
  const float maxPosDiffCoeff = std::sin(azimuthalResolution) / std::cos(azimuthalResolution + angleBeamNormal);

  // Loop over scan lines
  #pragma omp parallel for num_threads(this->NbThreads) schedule(guided) firstprivate(maxPosDiffCoeff)
  for (int scanLine = 0; scanLine < static_cast<int>(this->NbLaserRings); ++scanLine)
  {
    // Useful shortcuts
    const PointCloud& scanLineCloud = *(this->ScanLines[scanLine]);
    const int Npts = scanLineCloud.size();

    // If the line is almost empty, skip it
    if (this->IsScanLineAlmostEmpty(Npts))
    {
      for (int index = 0; index < Npts; ++index)
        this->IsPointValid[scanLine][index].reset();
      continue;
    }

    // Invalidate first and last points: because of undistortion, the depth of
    // first and last points can not be compared
    for (int index = 0; index < this->NeighborWidth; ++index)
    {
      this->IsPointValid[scanLine][index].reset();
      this->IsPointValid[scanLine][Npts - 1 - index].reset();
    }

    // Loop over remaining points of the scan line
    for (int index = this->NeighborWidth; index < Npts - this->NeighborWidth; ++index)
    {
      const auto& currentPoint = scanLineCloud[index].getVector3fMap();
      const float L = currentPoint.norm();
      // Invalidate points which are too close from the sensor
      if (L < this->MinDistanceToSensor)
      {
        this->IsPointValid[scanLine][index].reset();
      }

      // Compute maximal acceptable distance of two consecutive neighbors
      // aquired by the same laser, considering they lay on the same plane which
      // is not too oblique relatively to Lidar ray.
      // Check that this expected distance is not below range measurements noise.
      const float maxPosDiff = std::max(L * maxPosDiffCoeff, 0.02f);
      const float sqMaxPosDiff = maxPosDiff * maxPosDiff;

      // Invalidate occluded points due to depth gap or parallel beam.
      // If the distance between two successive points is bigger than the
      // expected length, it means that there is a depth gap. In this case, we
      // must invalidate the farthests points which belong to the occluded area.
      const auto& nextPoint = scanLineCloud[index + 1].getVector3fMap();
      if ((nextPoint - currentPoint).squaredNorm() > sqMaxPosDiff)
      {
        // If current point is the closest, next part is invalidated, starting from next point
        if (L < nextPoint.norm())
        {
          this->IsPointValid[scanLine][index + 1].reset();
          for (int i = index + 1; i < index + this->NeighborWidth; ++i)
          {
            const auto& Y  = scanLineCloud[i].getVector3fMap();
            const auto& Yn = scanLineCloud[i + 1].getVector3fMap();
            // If there is a new gap in the neighborhood,
            // the remaining points of the neighborhood are kept.
            if ((Yn - Y).squaredNorm() > sqMaxPosDiff)
              break;
            // Otherwise, the current neighbor point is disabled
            this->IsPointValid[scanLine][i + 1].reset();
          }
        }
        // If current point is the farthest, invalidate previous part, starting from current point
        else
        {
          this->IsPointValid[scanLine][index].reset();
          for (int i = index - 1; i > index - this->NeighborWidth; --i)
          {
            const auto& Yp = scanLineCloud[i].getVector3fMap();
            const auto&  Y = scanLineCloud[i + 1].getVector3fMap();
            // If there is a new gap in the neighborhood,
            // the remaining points of the neighborhood are kept.
            if ((Y - Yp).squaredNorm() > sqMaxPosDiff)
              break;
            // Otherwise, the previous neighbor point is disabled
            this->IsPointValid[scanLine][i].reset();
          }
        }
      }
    }
  }
}

//-----------------------------------------------------------------------------
void SpinningSensorKeypointExtractor::ComputeCurvature()
{
  const float sqDistToLineThreshold = this->DistToLineThreshold * this->DistToLineThreshold;  // [m²]
  const float sqDepthDistCoeff = 0.25;
  const float minDepthGapDist = 1.5;  // [m]

  // loop over scans lines
  #pragma omp parallel for num_threads(this->NbThreads) schedule(guided) \
          firstprivate(sqDistToLineThreshold, sqDepthDistCoeff, minDepthGapDist)
  for (int scanLine = 0; scanLine < static_cast<int>(this->NbLaserRings); ++scanLine)
  {
    // Useful shortcuts
    const PointCloud& scanLineCloud = *(this->ScanLines[scanLine]);
    const int Npts = scanLineCloud.size();

    // if the line is almost empty, skip it
    if (this->IsScanLineAlmostEmpty(Npts))
    {
      continue;
    }

    // loop over points in the current scan line
    // TODO : deal with spherical case : index=0 is neighbor of index=Npts-1
    for (int index = this->NeighborWidth; (index + this->NeighborWidth) < Npts; ++index)
    {
      // Skip curvature computation for invalid points
      if (this->IsPointValid[scanLine][index].none())
      {
        continue;
      }

      // central point
      const Point& currentPoint = scanLineCloud[index];
      const Eigen::Vector3f centralPoint = currentPoint.getVector3fMap();

      // compute intensity gap
      // CHECK : do not use currentPoint.intensity?
      const Point& previousPoint = scanLineCloud[index - 1];
      const Point& nextPoint = scanLineCloud[index + 1];
      this->IntensityGap[scanLine][index] = std::abs(nextPoint.intensity - previousPoint.intensity);

      // We will compute the line that fits the neighbors located before the current point.
      // We will do the same for the neighbors located after the current point.
      // We will then compute the angle between these two lines as an approximation
      // of the "sharpness" of the current point.
      std::vector<int> leftNeighbors(this->NeighborWidth);
      std::vector<int> rightNeighbors(this->NeighborWidth);
      LineFitting leftLine, rightLine;

      // Fill left and right neighborhoods, from central point to sides.
      // /!\ The way the neighbors are added to the vectors matters,
      // especially when computing the saliency
      for (int j = index - 1; j >= index - this->NeighborWidth; --j)
        leftNeighbors[index - 1 - j] = j;
      for (int j = index + 1; j <= index + this->NeighborWidth; ++j)
        rightNeighbors[j - index - 1] = j;

      // Fit line on the left and right neighborhoods and
      // Indicate if they are flat or not
      const bool leftFlat = leftLine.FitPCAAndCheckConsistency(scanLineCloud, leftNeighbors);
      const bool rightFlat = rightLine.FitPCAAndCheckConsistency(scanLineCloud, rightNeighbors);

      // Measurement of the depth gap
      float distLeft = 0., distRight = 0.;

      // If both neighborhoods are flat, we can compute the angle between them
      // as an approximation of the sharpness of the current point
      if (leftFlat && rightFlat)
      {
        // We check that the current point is not too far from its
        // neighborhood lines. This is because we don't want a point
        // to be considered as an angle point if it is due to gap
        distLeft = leftLine.SquaredDistanceToPoint(centralPoint);
        distRight = rightLine.SquaredDistanceToPoint(centralPoint);

        // If current point is not too far from estimated lines,
        // save the sin of angle between these two lines
        if ((distLeft < sqDistToLineThreshold) && (distRight < sqDistToLineThreshold))
          this->Angles[scanLine][index] = (leftLine.Direction.cross(rightLine.Direction)).norm();
      }

      // Here one side of the neighborhood is non flat.
      // Hence it is not worth to estimate the sharpness.
      // Only the gap will be considered here.
      // CHECK : looks strange to estimate depth gap without considering current point
      else if (!leftFlat && rightFlat)
      {
        distLeft = std::numeric_limits<float>::max();
        for (const auto& leftNeighborId: leftNeighbors)
        {
          const auto& leftNeighbor = scanLineCloud[leftNeighborId].getVector3fMap();
          distLeft = std::min(distLeft, rightLine.SquaredDistanceToPoint(leftNeighbor));
        }
        distLeft *= sqDepthDistCoeff;
      }
      else if (leftFlat && !rightFlat)
      {
        distRight = std::numeric_limits<float>::max();
        for (const auto& rightNeighborId: rightNeighbors)
        {
          const auto& rightNeighbor = scanLineCloud[rightNeighborId].getVector3fMap();
          distRight = std::min(distRight, leftLine.SquaredDistanceToPoint(rightNeighbor));
        }
        distRight *= sqDepthDistCoeff;
      }

      // No neighborhood is flat.
      // We will compute saliency of the current keypoint from its far neighbors.
      else
      {
        // Compute salient point score
        const float sqCurrDepth = centralPoint.squaredNorm();
        bool hasLeftEncounteredDepthGap = false;
        bool hasRightEncounteredDepthGap = false;

        std::vector<int> farNeighbors;
        farNeighbors.reserve(2 * this->NeighborWidth);

        // The salient point score is the distance between the current point
        // and the points that have a depth gap with the current point
        // CHECK : consider only consecutive far neighbors, starting from the central point.
        for (const auto& leftNeighborId: leftNeighbors)
        {
          // Left neighborhood depth gap computation
          if (std::abs(scanLineCloud[leftNeighborId].getVector3fMap().squaredNorm() - sqCurrDepth) > minDepthGapDist)
          {
            hasLeftEncounteredDepthGap = true;
            farNeighbors.emplace_back(leftNeighborId);
          }
          else if (hasLeftEncounteredDepthGap)
            break;
        }
        for (const auto& rightNeighborId: rightNeighbors)
        {
          // Right neigborhood depth gap computation
          if (std::abs(scanLineCloud[rightNeighborId].getVector3fMap().squaredNorm() - sqCurrDepth) > minDepthGapDist)
          {
            hasRightEncounteredDepthGap = true;
            farNeighbors.emplace_back(rightNeighborId);
          }
          else if (hasRightEncounteredDepthGap)
            break;
        }

        // If there are enough neighbors with a big depth gap,
        // we propose to compute the saliency of the current point
        // as the distance between the line that roughly fits the far neighbors
        // with a depth gap and the current point
        if (farNeighbors.size() > static_cast<unsigned int>(this->NeighborWidth))
        {
          LineFitting farNeighborsLine;
          farNeighborsLine.FitPCA(scanLineCloud, farNeighbors);
          this->Saliency[scanLine][index] = farNeighborsLine.SquaredDistanceToPoint(centralPoint);
        }
      }

      // Store max depth gap
      this->DepthGap[scanLine][index] = std::max(distLeft, distRight);
    }
  }
}

//-----------------------------------------------------------------------------
void SpinningSensorKeypointExtractor::SetKeyPointsLabels()
{
  const float sqEdgeSaliencythreshold = this->EdgeSaliencyThreshold * this->EdgeSaliencyThreshold;
  const float sqEdgeDepthGapThreshold = this->EdgeDepthGapThreshold * this->EdgeDepthGapThreshold;

  // loop over the scan lines
  #pragma omp parallel for num_threads(this->NbThreads) schedule(guided) \
          firstprivate(sqEdgeSaliencythreshold, sqEdgeDepthGapThreshold)
  for (int scanLine = 0; scanLine < static_cast<int>(this->NbLaserRings); ++scanLine)
  {
    const int Npts = this->ScanLines[scanLine]->size();

    // if the line is almost empty, skip it
    if (this->IsScanLineAlmostEmpty(Npts))
    {
      continue;
    }

    // Sort the curvature score in a decreasing order
    std::vector<size_t> sortedDepthGapIdx  = Utils::SortIdx(this->DepthGap    [scanLine], false);
    std::vector<size_t> sortedAnglesIdx    = Utils::SortIdx(this->Angles      [scanLine], false);
    std::vector<size_t> sortedSaliencyIdx  = Utils::SortIdx(this->Saliency    [scanLine], false);
    std::vector<size_t> sortedIntensityGap = Utils::SortIdx(this->IntensityGap[scanLine], false);

    // Add edge according to criterion
    auto addEdgesUsingCriterion = [this, scanLine, Npts](const std::vector<size_t>& sortedValuesIdx,
                                                         const std::vector<std::vector<float>>& values,
                                                         float threshold,
                                                         int invalidNeighborhoodSize)
    {
      for (const auto& index: sortedValuesIdx)
      {
        // Check criterion threshold
        // If criterion is not respected, break loop as indices are sorted in decreasing order.
        if (values[scanLine][index] < threshold)
          break;

        // If the point is invalid as edge, continue
        if (!this->IsPointValid[scanLine][index][Keypoint::EDGE])
          continue;

        // Else indicate that the point is an edge
        this->Label[scanLine][index].set(Keypoint::EDGE);

        // Invalid its neighbors
        const int indexBegin = std::max(0,        static_cast<int>(index - invalidNeighborhoodSize));
        const int indexEnd   = std::min(Npts - 1, static_cast<int>(index + invalidNeighborhoodSize));
        for (int j = indexBegin; j <= indexEnd; ++j)
          this->IsPointValid[scanLine][j].reset(Keypoint::EDGE);
      }
    };

    // Edges using depth gap
    addEdgesUsingCriterion(sortedDepthGapIdx, this->DepthGap, sqEdgeDepthGapThreshold, this->NeighborWidth - 1);
    // Edges using angles
    addEdgesUsingCriterion(sortedAnglesIdx, this->Angles, this->EdgeSinAngleThreshold, this->NeighborWidth);
    // Edges using saliency
    addEdgesUsingCriterion(sortedSaliencyIdx, this->Saliency, sqEdgeSaliencythreshold, this->NeighborWidth - 1);
    // Edges using intensity
    addEdgesUsingCriterion(sortedIntensityGap, this->IntensityGap, this->EdgeIntensityGapThreshold, 1);

    // Planes (using angles)
    for (int k = Npts - 1; k >= 0; --k)
    {
      size_t index = sortedAnglesIdx[k];
      const float sinAngle = this->Angles[scanLine][index];

      // thresh
      if (sinAngle > this->PlaneSinAngleThreshold)
        break;

      // if the point is invalid as plane or sinAngle value is unset, continue
      if (!this->IsPointValid[scanLine][index][Keypoint::PLANE] || sinAngle < 1e-6)
        continue;

      // else indicate that the point is a planar one
      this->Label[scanLine][index].set(Keypoint::PLANE);

      // Invalid its neighbors so that we don't have too
      // many planar keypoints in the same region. This is
      // required because of the k-nearest search + plane
      // approximation realized in the odometry part. Indeed,
      // if all the planar points are on the same scan line the
      // problem is degenerated since all the points are distributed
      // on a line.
      const int indexBegin = std::max(0,        static_cast<int>(index - 4));
      const int indexEnd   = std::min(Npts - 1, static_cast<int>(index + 4));
      for (int j = indexBegin; j <= indexEnd; ++j)
        this->IsPointValid[scanLine][j].reset(Keypoint::PLANE);
    }

    // Blobs Points
    // CHECK : why using only 1 point over 3?
    // TODO : disable blobs if not required
    for (int index = 0; index < Npts; index += 3)
    {
      if (this->IsPointValid[scanLine][index][Keypoint::BLOB])
        this->Label[scanLine][index].set(Keypoint::BLOB);
    }
  }

  for (unsigned int scanLine = 0; scanLine < this->NbLaserRings; ++scanLine)
  {
    const PointCloud& scanLineCloud = *(this->ScanLines[scanLine]);
    for (unsigned int index = 0; index < scanLineCloud.size(); ++index)
    {
      for (const auto& k : KeypointTypes)
      {
        if (this->Label[scanLine][index][k])
        {
          this->IsPointValid[scanLine][index].set(k);
          this->Keypoints[k]->push_back(scanLineCloud[index]);
        }
      }
    }
  }
}

//-----------------------------------------------------------------------------
void SpinningSensorKeypointExtractor::EstimateAzimuthalResolution()
{
  // Compute horizontal angle values between successive points
  std::vector<float> angles;
  angles.reserve(this->Scan->size());
  for (const PointCloud::Ptr& scanLine : this->ScanLines)
  {
    for (unsigned int index = 1; index < scanLine->size(); ++index)
    {
      // Compute horizontal angle between two measurements
      // WARNING: to be correct, the points need to be in the LIDAR sensor
      // coordinates system, where the sensor is spinning around Z axis.
      Eigen::Map<const Eigen::Vector2f> p1(scanLine->at(index - 1).data);
      Eigen::Map<const Eigen::Vector2f> p2(scanLine->at(index).data);
      float angle = std::abs(std::acos(p1.dot(p2) / (p1.norm() * p2.norm())));

      // Keep only angles greater than 0 to avoid dual return issues
      if (angle > 1e-4)
        angles.push_back(angle);
    }
  }

  // A minimum number of angles is needed to get a trustable estimator
  if (angles.size() < 100)
  {
    PRINT_WARNING("Not enough points to estimate azimuthal resolution");
    return;
  }

  // Estimate azimuthal resolution from these angles
  std::sort(angles.begin(), angles.end());
  unsigned int maxInliersIdx = angles.size();
  float maxAngle = Utils::Deg2Rad(5.);
  float medianAngle = 0.;
  // Iterate until only angles between direct LiDAR beam neighbors remain.
  // The max resolution angle is decreased at each iteration.
  while (maxAngle > 1.8 * medianAngle)
  {
    maxInliersIdx = std::upper_bound(angles.begin(), angles.begin() + maxInliersIdx, maxAngle) - angles.begin();
    medianAngle = angles[maxInliersIdx / 2];
    maxAngle = std::min(medianAngle * 2., maxAngle / 1.8);
  }
  this->AzimuthalResolution = medianAngle;
  std::cout << "LiDAR's azimuthal resolution estimated to " << Utils::Rad2Deg(this->AzimuthalResolution) << "°" << std::endl;
}

//-----------------------------------------------------------------------------
std::unordered_map<std::string, std::vector<float>> SpinningSensorKeypointExtractor::GetDebugArray() const
{
  auto get1DVector = [this](auto const& vector2d)
  {
    std::vector<float> v(this->Scan->size());
    std::vector<int> indexByScanLine(this->NbLaserRings, 0);
    for (unsigned int i = 0; i < this->Scan->size(); i++)
    {
      const auto& laserId = this->Scan->points[i].laser_id;
      v[i] = vector2d[laserId][indexByScanLine[laserId]];
      indexByScanLine[laserId]++;
    }
    return v;
  }; // end of lambda expression

  auto get1DVectorFromFlag = [this](auto const& vector2d, int flag)
  {
    std::vector<float> v(this->Scan->size());
    std::vector<int> indexByScanLine(this->NbLaserRings, 0);
    for (unsigned int i = 0; i < this->Scan->size(); i++)
    {
      const auto& laserId = this->Scan->points[i].laser_id;
      v[i] = vector2d[laserId][indexByScanLine[laserId]][flag];
      indexByScanLine[laserId]++;
    }
    return v;
  }; // end of lambda expression

  std::unordered_map<std::string, std::vector<float>> map;
  map["sin_angle"]      = get1DVector(this->Angles);
  map["saliency"]       = get1DVector(this->Saliency);
  map["depth_gap"]      = get1DVector(this->DepthGap);
  map["intensity_gap"]  = get1DVector(this->IntensityGap);
  map["edge_keypoint"]  = get1DVectorFromFlag(this->Label, Keypoint::EDGE);
  map["plane_keypoint"] = get1DVectorFromFlag(this->Label, Keypoint::PLANE);
  map["blob_keypoint"]  = get1DVectorFromFlag(this->Label, Keypoint::BLOB);
  map["edge_validity"]  = get1DVectorFromFlag(this->IsPointValid, Keypoint::EDGE);
  map["plane_validity"] = get1DVectorFromFlag(this->IsPointValid, Keypoint::PLANE);
  map["blob_validity"]  = get1DVectorFromFlag(this->IsPointValid, Keypoint::BLOB);
  return map;
}

} // end of LidarSlam namespace

ext: cxx

max_stars_repo_name: jpouderoux/LidarSlam

max_issues_repo_name: jpouderoux/LidarSlam

max_forks_repo_name: jpouderoux/LidarSlam


text:
#ifndef SCATTERING_H
#define SCATTERING_H

#include <iostream>
#include <cstdlib>
#include <boost/math/special_functions/bessel.hpp>
#include <complex>
using namespace std;

#include "potentials.hpp"
#include "numerov.hpp"
#include "writeout.hpp"
#include "constant.hpp"

// Calculation of the scattering amplitude for single-channel potential scattering.

complex<double> Smatrix(const CentralPotentials pot, const double energy, const int l, const double h2over2mu, const vector<double> & parameters,
	const int nmesh, const double mesh);
#endif