// [[Rcpp::plugins(cpp14)]]
#include <Rcpp.h>
// [[Rcpp::depends(RcppEigen)]]
#include <RcppEigen.h>
// [[Rcpp::depends(RcppProgress)]]
#include <progress.hpp>

using namespace Rcpp;

#include <Eigen/Eigenvalues>
#include <algorithm>
#include <numeric>
#include <random>
#include <string>
#include <vector>

#include "convergence.hh"
#include "options.hh"
#include "parameters.hh"
#include "rcpp_util.hh"
#include "regression.hh"
#include "regression_factored.hh"
#include "residual.hh"
#include "sgvb_regression_inference.hh"
#include "tuple_util.hh"
#include "kqtl_model.hh"

#ifndef RCPP_KQTL_HH_
#define RCPP_KQTL_HH_

using Mat = Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic>;
using Vec = Eigen::Matrix<float, Eigen::Dynamic, 1>;
using SpMat = Eigen::SparseMatrix<float, Eigen::ColMajor>;
using Scalar = Mat::Scalar;
using Index = Mat::Index;

#include "rcpp_kqtl_util.hh"
#include "rcpp_kernel_util.hh"
#include "rcpp_zscore_util.hh"
#include "rcpp_kqtl_regression.hh"

#endif


//==================================================================================================
/*!
  @file

  @copyright 2012-2015 NumScale SAS

  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_SIMD_CONSTANT_DEFINITION_POWLARGELIM_HPP_INCLUDED
#define BOOST_SIMD_CONSTANT_DEFINITION_POWLARGELIM_HPP_INCLUDED

#include <boost/simd/config.hpp>
#include <boost/simd/detail/brigand.hpp>
#include <boost/simd/detail/dispatch.hpp>
#include <boost/simd/detail/constant_traits.hpp>
#include <boost/dispatch/function/make_callable.hpp>
#include <boost/dispatch/hierarchy/functions.hpp>
#include <boost/dispatch/as.hpp>

namespace boost { namespace simd
{
  namespace tag
  {
    struct powlargelim_ : boost::dispatch::constant_value_<powlargelim_>
    {
      BOOST_DISPATCH_MAKE_CALLABLE(ext,powlargelim_,boost::dispatch::constant_value_<powlargelim_>);
      BOOST_SIMD_REGISTER_CONSTANT(0, 0x44ffe000UL, 0x40cfff8000000000ULL);
    };
  }

  namespace ext
  {
    BOOST_DISPATCH_FUNCTION_DECLARATION(tag,powlargelim_);
  }

  namespace detail
  {
    BOOST_DISPATCH_CALLABLE_DEFINITION(tag::powlargelim_,powlargelim);
  }

  template<typename T> BOOST_FORCEINLINE auto Powlargelim()
  BOOST_NOEXCEPT_DECLTYPE(detail::powlargelim( boost::dispatch::as_<T>{}))
  {
    return detail::powlargelim( boost::dispatch::as_<T>{} );
  }
} }

#endif


#ifndef LWTNN_UTILS_FAST_GRAPH_H
#define LWTNN_UTILS_FAST_GRAPH_H

#include "lwtnn/lightweight_network_config.hh"
#include "lwtnn/generic/eigen_typedefs.hh"

#include <Eigen/Dense>

namespace lwt {

  struct InputOrder;

namespace generic {

  template<typename T> class Graph;
  template<typename T> class FastInputPreprocessor;
  template<typename T> class FastInputVectorPreprocessor;

  template<typename T>
  using NodeVec = std::vector<VectorX<T>>;
  template<typename T>
  using SeqNodeVec = std::vector<MatrixX<T>>;

  namespace internal {
    struct SourceIndices
    {
      std::vector<size_t> scalar;
      std::vector<size_t> sequence;
    };
  }

  // Graph class
  template<typename T>
  class FastGraph
  {
  public:

    // In cases where the graph has multiple outputs, we have to
    // define a "default" output, so that calling "compute" with no
    // output specified doesn't lead to ambiguity.
    FastGraph(const GraphConfig& config, const InputOrder& order,
              std::string default_output = "");

    ~FastGraph();
    FastGraph(FastGraph&) = delete;
    FastGraph& operator=(FastGraph&) = delete;

    // The simpler "compute" function
    VectorX<T> compute(const NodeVec<T>&, const SeqNodeVec<T>& = {}) const;

    // the other "compute" which allows you to select an arbitrary output
    VectorX<T> compute(const NodeVec<T>&, const SeqNodeVec<T>&, size_t) const;

  private:
    typedef FastInputPreprocessor<T> IP;
    typedef FastInputVectorPreprocessor<T> IVP;
    typedef std::vector<IP> Preprocs;
    typedef std::vector<IVP> VecPreprocs;

    Graph<T> m_graph;
    Preprocs m_preprocs;
    VecPreprocs m_vec_preprocs;
    size_t m_default_output;
    // the mapping from a node in the network to a user input node
    internal::SourceIndices m_input_indices;
  };
} // namespace generic
} // namespace lwt

#include "FastGraph.tcc"

#endif


/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

/*
 Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
 Copyright (C) 2003, 2004, 2005, 2006, 2007 StatPro Italia srl
 Copyright (C) 2006, 2008 Ferdinando Ametrano
 Copyright (C) 2010 Andre Miemiec

 This file is part of QuantLib, a free-software/open-source library
 for financial quantitative analysts and developers - http://quantlib.org/

 QuantLib is free software: you can redistribute it and/or modify it
 under the terms of the QuantLib license.  You should have received a
 copy of the license along with this program; if not, please email
 <quantlib-dev@lists.sf.net>. The license is also available online at
 <http://quantlib.org/license.shtml>.

 This program is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE.  See the license for more details.
*/

/*! \file irregularswap.hpp
    \brief Irregular fixed-rate vs Libor swap
*/

#ifndef quantlib_irregular_swap_hpp
#define quantlib_irregular_swap_hpp

#include <ql/cashflows/fixedratecoupon.hpp>
#include <ql/cashflows/iborcoupon.hpp>
#include <ql/instruments/swap.hpp>
#include <ql/time/daycounter.hpp>
#include <ql/time/schedule.hpp>
#include <boost/optional.hpp>

namespace QuantLib {

    class IborIndex;

    //! Irregular swap: fixed vs floating leg
    class IrregularSwap : public Swap {
      public:
        enum Type { Receiver = -1, Payer = 1 };
        class arguments;
        class results;
        class engine;
        IrregularSwap(
            Type type,
            const Leg& fixLeg,
            const Leg& floatLeg);
        //! \name Inspectors
        //@{
        Type type() const;

        const Leg& fixedLeg() const;
        const Leg& floatingLeg() const;
        //@}

        //! \name Results
        //@{
        Real fixedLegBPS() const;
        Real fixedLegNPV() const;
        Rate fairRate() const;

        Real floatingLegBPS() const;
        Real floatingLegNPV() const;
        Spread fairSpread() const;
        //@}
        // other
        void setupArguments(PricingEngine::arguments* args) const override;
        void fetchResults(const PricingEngine::results*) const override;

      private:
        void setupExpired() const override;
        Type type_;

        // results
        mutable Rate fairRate_;
        mutable Spread fairSpread_;
    };

    //! %Arguments for irregular-swap calculation
    class IrregularSwap::arguments : public Swap::arguments {
      public:
        arguments() : type(Receiver){}
        Type type;

        std::vector<Date> fixedResetDates;
        std::vector<Date> fixedPayDates;
        std::vector<Real> fixedCoupons;
        std::vector<Real> fixedNominals;

        std::vector<Date> floatingResetDates;
        std::vector<Date> floatingFixingDates;
        std::vector<Date> floatingPayDates;
        std::vector<Time> floatingAccrualTimes;
        std::vector<Real> floatingNominals;
        std::vector<Spread> floatingSpreads;
        std::vector<Real> floatingCoupons;

        void validate() const override;
    };

    //! %Results from irregular-swap calculation
    class IrregularSwap::results : public Swap::results {
      public:
        Rate fairRate;
        Spread fairSpread;
        void reset() override;
    };

    class IrregularSwap::engine : public GenericEngine<IrregularSwap::arguments,
                                                       IrregularSwap::results> {};

    // inline definitions

    inline IrregularSwap::Type IrregularSwap::type() const {
        return type_;
    }

    inline const Leg& IrregularSwap::fixedLeg() const {
        return legs_[0];
    }

    inline const Leg& IrregularSwap::floatingLeg() const {
        return legs_[1];
    }

    std::ostream& operator<<(std::ostream& out,
                             IrregularSwap::Type t);

}

#endif


#ifndef PYBNESIAN_FACTORS_DISCRETE_DISCRETE_INDICES_HPP
#define PYBNESIAN_FACTORS_DISCRETE_DISCRETE_INDICES_HPP

#include <arrow/compute/api.h>
#include <Eigen/Dense>
#include <dataset/dataset.hpp>
#include <factors/assignment.hpp>
#include <util/hash_utils.hpp>

using dataset::DataFrame;
using Eigen::VectorXi;

namespace factors::discrete {

void check_is_string_dictionary(const std::shared_ptr<arrow::DictionaryArray>& dict, const std::string& variable);

template <typename ArrowType>
void sum_to_discrete_indices_null(VectorXi& accum_indices,
                                  Array_ptr& indices,
                                  int stride,
                                  Buffer_ptr& combined_bitmap) {
    using ArrayType = typename arrow::TypeTraits<ArrowType>::ArrayType;
    auto dwn_indices = std::static_pointer_cast<ArrayType>(indices);

    auto raw_combined_bitmap = combined_bitmap->data();
    for (auto i = 0, j = 0; i < indices->length(); ++i) {
        if (util::bit_util::GetBit(raw_combined_bitmap, i)) {
            accum_indices(j++) += dwn_indices->Value(i) * stride;
        }
    }
}

void sum_to_discrete_indices_null(VectorXi& accum_indices, Array_ptr& indices, int stride, Buffer_ptr& combined_bitmap);

template <typename ArrowType>
void sum_to_discrete_indices(VectorXi& accum_indices, Array_ptr& indices, int stride) {
    using ArrayType = typename arrow::TypeTraits<ArrowType>::ArrayType;
    using EigenMap = Map<const Matrix<typename ArrowType::c_type, Dynamic, 1>>;
    auto dwn_indices = std::static_pointer_cast<ArrayType>(indices);
    auto* raw_values = dwn_indices->raw_values();
    const EigenMap map_eigen(raw_values, indices->length());
    accum_indices += map_eigen.template cast<int>() * stride;
}

void sum_to_discrete_indices(VectorXi& accum_indices, Array_ptr& indices, int stride);

template <bool contains_null>
VectorXi discrete_indices(const DataFrame& df,
                          const std::string& variable,
                          const std::vector<std::string>& evidence,
                          const VectorXi& strides) {
    if constexpr (contains_null) {
        auto combined_bitmap = df.combined_bitmap(variable, evidence);

        auto valid_rows = util::bit_util::non_null_count(combined_bitmap, df->num_rows());

        VectorXi indices = VectorXi::Zero(valid_rows);

        auto dict_variable = std::static_pointer_cast<arrow::DictionaryArray>(df.col(variable));
        auto variable_indices = dict_variable->indices();

        sum_to_discrete_indices_null(indices, variable_indices, strides(0), combined_bitmap);

        int i = 1;
        for (auto it = evidence.begin(), end = evidence.end(); it != end; ++it, ++i) {
            auto dict_evidence = std::static_pointer_cast<arrow::DictionaryArray>(df.col(*it));
            auto evidence_indices = dict_evidence->indices();
            sum_to_discrete_indices_null(indices, evidence_indices, strides(i), combined_bitmap);
        }

        return indices;
    } else {
        VectorXi indices = VectorXi::Zero(df->num_rows());

        auto dict_variable = std::static_pointer_cast<arrow::DictionaryArray>(df.col(variable));
        auto variable_indices = dict_variable->indices();

        sum_to_discrete_indices(indices, variable_indices, strides(0));

        int i = 1;
        for (auto it = evidence.begin(), end = evidence.end(); it != end; ++it, ++i) {
            auto dict_evidence = std::static_pointer_cast<arrow::DictionaryArray>(df.col(*it));
            auto evidence_indices = dict_evidence->indices();
            sum_to_discrete_indices(indices, evidence_indices, strides(i));
        }

        return indices;
    }
}

VectorXi discrete_indices(const DataFrame& df,
                          const std::string& variable,
                          const std::vector<std::string>& evidence,
                          const VectorXi& strides);

template <bool contains_null>
VectorXi discrete_indices(const DataFrame& df, const std::vector<std::string>& variables, const VectorXi& strides) {
    if constexpr (contains_null) {
        auto combined_bitmap = df.combined_bitmap(variables);

        auto valid_rows = util::bit_util::non_null_count(combined_bitmap, df->num_rows());

        VectorXi indices = VectorXi::Zero(valid_rows);

        int i = 0;
        for (auto it = variables.begin(), end = variables.end(); it != end; ++it, ++i) {
            auto dict_variable = std::static_pointer_cast<arrow::DictionaryArray>(df.col(*it));
            auto variable_indices = dict_variable->indices();
            sum_to_discrete_indices_null(indices, variable_indices, strides(i), combined_bitmap);
        }

        return indices;
    } else {
        VectorXi indices = VectorXi::Zero(df->num_rows());

        int i = 0;
        for (auto it = variables.begin(), end = variables.end(); it != end; ++it, ++i) {
            auto dict_variable = std::static_pointer_cast<arrow::DictionaryArray>(df.col(*it));
            auto variable_indices = dict_variable->indices();
            sum_to_discrete_indices(indices, variable_indices, strides(i));
        }

        return indices;
    }
}

VectorXi discrete_indices(const DataFrame& df, const std::vector<std::string>& variables, const VectorXi& strides);

std::pair<VectorXi, VectorXi> create_cardinality_strides(const DataFrame& df,
                                                         const std::string& variable,
                                                         const std::vector<std::string>& evidence);
std::pair<VectorXi, VectorXi> create_cardinality_strides(const DataFrame& df,
                                                         const std::vector<std::string>& variables);

VectorXi joint_counts(const DataFrame& df,
                      const std::string& variable,
                      const std::vector<std::string>& evidence,
                      const VectorXi& cardinality,
                      const VectorXi& strides);

VectorXi marginal_counts(const VectorXi& joint_counts, int index, const VectorXi& cardinality, const VectorXi& strides);

std::vector<Array_ptr> discrete_slice_indices(const DataFrame& df,
                                              const std::vector<std::string>& discrete_vars,
                                              const VectorXi& indices,
                                              int num_factors);

void check_domain_variable(const DataFrame& df,
                           const std::string& variable,
                           const std::vector<std::string>& variable_values);

}  // namespace factors::discrete

#endif  // PYBNESIAN_FACTORS_DISCRETE_DISCRETE_INDICES_HPP


/**
 * @project zapdos
 * @file include/utils/SortHelpers.hpp
 * @author  S Roychowdhury < sroycode at gmail dot com >
 * @version 1.0.0
 *
 * @section LICENSE
 *
 * Copyright (c) 2018-2020 S Roychowdhury
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * @section DESCRIPTION
 *
 *  SortHelpers.hpp : Sort helpers for Standard Inclusion Headers
 *
 */
#ifndef _ZPDS_UTILS_SORT_HELPERS_HPP_
#define _ZPDS_UTILS_SORT_HELPERS_HPP_

#include <cstring>
#include <string>
#include <algorithm>
#include <sstream>
#include <boost/algorithm/string.hpp>
#include <functional>
#include <iomanip>
#include <map>
#include <cmath>
#include "utils/BaseUtils.hpp"

#define DR_BUFF_INT 10000
#define DR_BUFF_MAX std::numeric_limits<int32_t>::max()
#define DR_BUFF_MIN std::numeric_limits<int32_t>::min()

#define ZPDS_UINT64_MAX std::numeric_limits<uint64_t>::max()

/** Sort Helper functions start */

/**
 * MakeSortKey : make sort key for single item default
 *
 */
template <typename T>
static void MakeSortKey(std::ostream& o,  T t)
{
	throw zpds::BadCodeException("This type cannot be used in key");
}

/**
 * MakeSortKey : make sort key for single item uint64_t specialization
 *
 */
template<> void MakeSortKey(std::ostream& o, uint64_t t)
{
	t = ( t > DR_BUFF_MAX ) ? DR_BUFF_MAX : t;
	o << static_cast<uint64_t>( (t * DR_BUFF_INT) + std::numeric_limits<int64_t>::max() );
}

/**
 * MakeSortKey : make sort key for single item int64_t
 *
 */
template<> void MakeSortKey(std::ostream& o, int64_t t)
{
	t = ( t > DR_BUFF_MAX ) ? DR_BUFF_MAX : ( t < DR_BUFF_MIN ) ? DR_BUFF_MIN : t;
	o << static_cast<uint64_t>( ( (int64_t)t * DR_BUFF_INT) + ( (t>0) ? std::numeric_limits<int64_t>::max() : 0 ));
}

/**
 * MakeSortKey : make sort key for uint32_t specialization
 *
 */
template<> void MakeSortKey(std::ostream& o, uint32_t t)
{
	o << static_cast<uint64_t>( ( (int64_t)t * DR_BUFF_INT) + std::numeric_limits<int64_t>::max() );
}

/**
 * MakeSortKey : make sort key for int32_t specialization
 *
 */
template<> void MakeSortKey(std::ostream& o, int32_t t)
{
	o << static_cast<uint64_t>( ( (int64_t)t * DR_BUFF_INT) + ((t>0) ? std::numeric_limits<int64_t>::max() : 0 ));
}

/**
 * MakeSortKey : make sort key for single item double
 *
 */
template<> void MakeSortKey(std::ostream& o, double t)
{
	o << static_cast<uint64_t>( std::llround((long double)t * DR_BUFF_INT) + ((t>0) ? std::numeric_limits<int64_t>::max() : 0 ));
}

/**
 * MakeSortKey : make sort key for single item char
 *
 */
template<> void MakeSortKey(std::ostream& o, char t)
{
	o << t;
}

/**
 * MakeSortKey : variadic recursive for multiple sort
 *
 */
template<typename T, typename... Args>
static void MakeSortKey(std::ostream& o, T t, Args... args)
{
	MakeSortKey(o, t);
	MakeSortKey(o, args...);
}

/**
 * EncodeSortKey : encode key
 *
 */
template<typename... T>
static std::string EncodeSortKey (T... key)
{
	std::ostringstream ss;
	ss << std::setbase(16) << std::setfill ('0') << std::setw (16);
	MakeSortKey(ss, key...);
	return ss.str();
}

/** Sort Helper functions end */

#endif // _ZPDS_UTILS_SORT_HELPERS_HPP_


/*!
 * *****************************************************************************
 *   \file depthMapCreationHSBS_main.cpp
 *   \author moennen
 *   \brief
 *   \date 2018-02-19
 *   *****************************************************************************/

#include "utils/imgFileLst.h"
#include "utils/cv_utils.h"

#include <libopticalFlow/oclVarOpticalFlow.h>

#include "opencv2/cudastereo.hpp"

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>

#include <boost/filesystem.hpp>

#include <iostream>

using namespace std;
using namespace cv;
using namespace glm;
using namespace boost;

namespace
{
std::mt19937 rs_gen{0};

const std::array<std::string, 10> stripedVideoIdName = {
    {"0000", "0004", "0005", "0006", "0008", "0014", "0017", "0022", "0041", "0046"}};
const std::array<std::string, 2> invertVideoIdName = {{"0009", "0027"}};
const std::array<std::string, 13> ignoreVideoIdName = {{"0022",
                                                        "0023",
                                                        "0024",
                                                        "0026",
                                                        "0027",
                                                        "0028",
                                                        "0034",
                                                        "0035",
                                                        "0036",
                                                        "0038",
                                                        "0041",
                                                        "0046",
                                                        "0048"}};

//------------------------------------------------------------------------------
//
void resizeToMin( Mat& img, const uvec2 sampleSz )
{
   uvec2 imgSz( img.cols, img.rows );
   // random rescale
   const float ds = std::min( (float)sampleSz.y / imgSz.y, (float)sampleSz.x / imgSz.x );
   resize( img, img, Size(), ds, ds, CV_INTER_AREA );
}

//------------------------------------------------------------------------------
//
void split_hsbs( const Mat& img, Mat& right, Mat& left, const unsigned nHStripes = 0 )
{
   const uvec2 off = {0, 0};
   const uvec2 hSz = {img.cols / 2, img.rows - 2 * nHStripes};
   right = img( Rect( off.x, nHStripes + off.y, hSz.x - 2 * off.x, hSz.y - 2 * off.y ) ).clone();
   left = img( Rect( hSz.x + off.x, nHStripes + off.y, hSz.x - 2 * off.x, hSz.y - 2 * off.y ) )
              .clone();
}

//------------------------------------------------------------------------------
//
Mat hstrech( const Mat& img )
{
   Mat simg( img.rows, 2 * img.cols, CV_32FC3 );

#pragma omp parallel for
   for ( size_t y = 0; y < simg.rows; y++ )
   {
      vec3* simg_data = simg.ptr<vec3>( y );

      for ( size_t x = 0; x < simg.cols; x++ )
      {
         simg_data[x] = cv_utils::imsample32FC3<vec3>( img, vec2( 0.5 * x, y ) );
      }
   }

   return simg;
}

//------------------------------------------------------------------------------
//
Mat flowToImg( const Mat& flow, const bool leg = false )
{
   Mat flow_split[2];
   Mat t_split[3];
   Mat bgr;
   split( flow, flow_split );
   if ( leg )
   {
      t_split[0] = Mat::zeros( flow_split[0].size(), flow_split[0].type() );
      t_split[1] = flow_split[1];
      t_split[2] = flow_split[0];
      merge( t_split, 3, bgr );
   }
   else
   {
      Mat hsv;
      Mat magnitude, angle;
      cartToPolar( flow_split[0], flow_split[1], magnitude, angle, true );
      normalize( magnitude, magnitude, 0, 1, NORM_MINMAX );
      t_split[0] = angle;  // already in degrees - no normalization needed
      t_split[1] = Mat::ones( angle.size(), angle.type() );
      t_split[2] = magnitude;
      merge( t_split, 3, hsv );
      cvtColor( hsv, bgr, COLOR_HSV2BGR );
   }
   return bgr;
}

//------------------------------------------------------------------------------
//
Mat flowToErr( const Mat& flow, const Mat& imgFrom, const Mat& imgTo )
{
   Mat lk( flow.rows, flow.cols, CV_32FC1 );

#pragma omp parallel for
   for ( size_t y = 0; y < flow.rows; y++ )
   {
      float* lk_data = lk.ptr<float>( y );
      const vec2* flow_data = flow.ptr<vec2>( y );
      const vec3* from_data = imgFrom.ptr<vec3>( y );

      for ( size_t x = 0; x < flow.cols; x++ )
      {
         const vec2 f = flow_data[x];
         const vec3 from = from_data[x];
         const vec3 to = cv_utils::imsample32FC3<vec3>( imgTo, vec2( x, y ) + f );
         lk_data[x] = distance( from, to );
      }
   }

   return lk;
}

//------------------------------------------------------------------------------
//
bool processDepth( Mat& depth, const Mat& img, const Mat& undef, unsigned nIt )
{
   Mat curr( depth.rows, depth.cols, CV_32FC4 );
   // fill the first level
#pragma omp parallel for
   for ( unsigned y = 0; y < depth.rows; y++ )
   {
      const float* depthPtr = depth.ptr<float>( y );
      const float* undefPtr = undef.ptr<float>( y );
      const vec3* imgPtr = img.ptr<vec3>( y );
      vec4* currPtr = curr.ptr<vec4>( y );
      for ( unsigned x = 0; x < depth.cols; x++ )
      {
         const float& d = depthPtr[x];
         const vec3& color = imgPtr[x];
         const bool isUndef = undefPtr[x] < 0.5;

         currPtr[x] = vec4( isUndef ? -1.0 : d, color.x, color.y, color.z );
      }
   }
   Mat next( depth.rows, depth.cols, CV_32FC4 );

   unsigned nUndef = 0;
   for ( unsigned it = 0; it < nIt; ++it )
   {
      nUndef = 0;

#pragma omp parallel for
      for ( unsigned y = 0; y < depth.rows; y++ )
      {
         const vec4* currPtr = curr.ptr<vec4>( y );
         vec4* nextPtr = next.ptr<vec4>( y );

         for ( unsigned x = 0; x < depth.cols; x++ )
         {
            const vec4& currVal = currPtr[x];
            nextPtr[x] = currVal;

            if ( currVal.x < 0.0 )
            {
#pragma omp atomic
               nUndef++;
               float w = 0.0;
               float d = 0.0;
               for ( int dy = -1; dy <= 1; dy++ )
               {
                  for ( int dx = -1; dx <= 1; dx++ )
                  {
                     const vec2 dpos( (float)x + (float)dx, (float)y + (float)dy );
                     const vec4 dval = cv_utils::imsample32F<vec4>( curr, dpos );

                     if ( dval.x > 0.0 )
                     {
                        float lw = ( currVal.y - dval.y ) * ( currVal.y - dval.y ) +
                                   ( currVal.z - dval.z ) * ( currVal.z - dval.z ) +
                                   ( currVal.w - dval.w ) * ( currVal.w - dval.w );
                        lw = exp( -lw / 0.01 );
                        w += lw;
                        d += lw * dval.x;
                     }
                  }
               }
               if ( w > 0.0 )
               {
                  nextPtr[x].x = d / w;
               }
            }
         }
      }
      if ( nUndef == 0 ) break;
      std::swap( curr, next );
   }

#pragma omp parallel for
   for ( unsigned y = 0; y < depth.rows; y++ )
   {
      const vec4* currPtr = curr.ptr<vec4>( y );
      float* depthPtr = depth.ptr<float>( y );
      for ( unsigned x = 0; x < depth.cols; x++ )
      {
         depthPtr[x] = currPtr[x].x;
      }
   }

   return nUndef == 0;
}

//------------------------------------------------------------------------------
//
bool flowToDisp(
    const Mat& flowR,
    const Mat& flowL,
    const Mat& imgFrom,
    const Mat& imgTo,
    Mat& disp,
    Mat& mask,
    const bool isInverted )
{
   disp = Mat( flowR.rows, flowR.cols, CV_32FC1 );
   mask = Mat( flowR.rows, flowR.cols, CV_8UC1 );

   Mat errR = flowToErr( flowR, imgFrom, imgTo );

#pragma omp parallel for
   for ( size_t y = 0; y < flowR.rows; y++ )
   {
      const vec2* f_row_r_data = flowR.ptr<vec2>( y );
      const float* err_data = errR.ptr<float>( y );
      const vec2* f_row_l_data = flowL.ptr<vec2>( y );

      float* d_row_data = disp.ptr<float>( y );
      unsigned char* u_row_data = mask.ptr<unsigned char>( y );

      for ( size_t x = 0; x < flowR.cols; x++ )
      {
         const vec2 mtR = f_row_r_data[x];
         const float dispR = sign( mtR.x ) * length( mtR );
         const vec2 mtRL = vec2( -1.0 ) * cv_utils::imsample32F<vec2>( flowL, vec2( x, y ) + mtR );
         const float dispRL = sign( mtRL.x ) * length( mtRL );

         const float dispReg = mix( dispR, dispRL, 0.5 );
         const bool undef = ( abs( mtR.y ) > 1.0 ) || ( abs( mtRL.y ) > 1.0 ) ||
                            ( err_data[x] > 0.31 ) || ( distance( mtR, mtRL ) > 0.75 );

         u_row_data[x] = undef ? 0 : 255;
         d_row_data[x] = ( isInverted ? 1.0 : -1.0 ) * dispReg;
      }
   }

   normalize( disp, disp, 0.0, 1.0, NORM_MINMAX, -1, mask );

   const float masked = ( 1.0f - ( cv::mean( mask )[0] / 255.0f ) );

   return masked < 0.65;
}
}

//------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------

const string keys =
    "{help h usage ? |         | print this message   }"
    "{@imgFileLst      |         | images list   }"
    "{@imgRootDir    |         | images root dir   }"
    "{@imgOutDir    |         | images output dir   }"
    "{startIdx    |0         |    }"
    "{show     |         |    }"
    "{nowrite     |        |    }";

int main( int argc, char* argv[] )
{
   CommandLineParser parser( argc, argv, keys );
   if ( parser.has( "help" ) )
   {
      parser.printMessage();
      return ( 0 );
   }

   const uvec2 maxSz = uvec2( 640, 480 );
   const bool toLinear = false;
   const float delayOnError = 100;
   const int startIdx = parser.get<int>( "startIdx" );

   const bool doShow = parser.get<bool>( "show" );
   const bool doWrite = !parser.get<bool>( "nowrite" );

   const filesystem::path outRootPath( parser.get<string>( "@imgOutDir" ) );

   // Create the list of image triplets

   ImgNFileLst<1> imgLst(
       parser.get<string>( "@imgFileLst" ).c_str(), parser.get<string>( "@imgRootDir" ).c_str() );
   if ( imgLst.size() == 0 )
   {
      cerr << "Invalid dataset : " << parser.get<string>( "@imgFileLst" ) << endl;
      return -1;
   }

   // Create the optical flow estimator
   OclVarOpticalFlow::params_t ofParams = OclVarOpticalFlow::getDefaultParams();
   ofParams.lambda = 0.19;
   OclVarOpticalFlow ofEstimator( maxSz.x, maxSz.y, false, ofParams );

   // left / right random swap
   uniform_int_distribution<> rs_left( 0, 1 );

   // Loop through the data
   for ( size_t i = startIdx; i < imgLst.size(); ++i )
   {
      const auto& data = imgLst[i];

      // load the current image
      // for ( size_t j = 0; j < 3; ++j )
      const size_t j = 0;
      {
         const string outBasename = filesystem::path( data[j] ).stem().string();
         const string videoIdname = outBasename.substr( 0, outBasename.find_first_of( "_" ) );

         const filesystem::path outVideoPath( videoIdname );

         const bool ignore =
             find( ignoreVideoIdName.begin(), ignoreVideoIdName.end(), videoIdname ) !=
             ignoreVideoIdName.end();
         if ( ignore ) continue;

         Mat img = cv_utils::imread32FC3( data[j], toLinear, true );

         const bool isStriped =
             find( stripedVideoIdName.begin(), stripedVideoIdName.end(), videoIdname ) !=
             stripedVideoIdName.end();

         const bool isInverted =
             find( invertVideoIdName.begin(), invertVideoIdName.end(), videoIdname ) !=
             invertVideoIdName.end();

         // split the current image
         Mat right, left;
         split_hsbs( img, right, left, isStriped ? ( img.rows - img.rows / 1.35 ) / 2 : 0 );
         // randomly swap left / right to avoid a potential right bias
         const bool doLeft = false;  // rs_left( rs_gen );
         if ( doLeft ) swap( right, left );

         right = hstrech( right );
         resizeToMin( right, maxSz );
         left = hstrech( left );
         resizeToMin( left, maxSz );

         // clone the image for output
         Mat oright = right.clone();

         // apply a blur to ease the optical flow estimation
         GaussianBlur( right, right, Size( 3, 3 ), 0.13 );
         GaussianBlur( left, left, Size( 3, 3 ), 0.13 );

         // compute the right to left optical flow
         ofEstimator.setImgSize( right.cols, right.rows );

         Mat ofRight( right.rows, right.cols, CV_32FC2 );
         ofEstimator.compute(
             reinterpret_cast<const float*>( left.ptr() ),
             reinterpret_cast<const float*>( right.ptr() ),
             right.cols,
             right.rows,
             reinterpret_cast<float*>( ofRight.ptr() ) );

         // filter on low disparities
         if ( cv::mean( cv::abs( ofRight ) )[0] < 1.0 ) continue;

         // compute the left to right optical flow
         Mat ofLeft( right.rows, right.cols, CV_32FC2 );
         ofEstimator.compute(
             reinterpret_cast<const float*>( right.ptr() ),
             reinterpret_cast<const float*>( left.ptr() ),
             right.cols,
             right.rows,
             reinterpret_cast<float*>( ofLeft.ptr() ) );

         // filter on low disparities
         if ( cv::mean( cv::abs( ofLeft ) )[0] < 1.0 ) continue;

         // compute the disparity and disparity mask
         Mat depth, mask;
         if ( !flowToDisp( ofRight, ofLeft, right, left, depth, mask, isInverted ^ doLeft ) )
            continue;

         cvtColor( oright, oright, COLOR_BGR2RGB );

         const filesystem::path fRight(
             videoIdname + "/" + outBasename + string( "_rgb" ) + ".png" );
         const filesystem::path fDepth( videoIdname + "/" + outBasename + string( "_d" ) + ".exr" );
         const filesystem::path fMask( videoIdname + "/" + outBasename + string( "_a" ) + ".png" );

         if ( doWrite )
         {
            imwrite( filesystem::path( outRootPath / fRight ).string().c_str(), oright * 255.0 );
            imwrite( filesystem::path( outRootPath / fDepth ).string().c_str(), depth );
            imwrite( filesystem::path( outRootPath / fMask ).string().c_str(), mask );
         }

         cout << fRight.string() << " " << fDepth.string() << " " << fMask.string();

         // if ( j == 2 )
         cout << endl;
         /*else
            cout << " ";*/

         // display
         if ( doShow )
         {
            // cvtColor( img, img, COLOR_BGR2RGB );
            // imshow( "Full", img );
            imshow( "Right", oright );
            cvtColor( left, left, COLOR_BGR2RGB );
            imshow( "Left", left );
            imshow( "Disp", depth );
            imshow( "Mask", mask );
            waitKey( 0 );
         }
      }
   }

   return ( 0 );
}


#include "tcdf/tcdf.h"

#include <Eigen/Dense>
#include <iostream>

int main(int argc, char** argv) {
	Eigen::MatrixXd x(5,6);
	Eigen::MatrixXd v(5,6);
	Eigen::MatrixXd res;

	x.setRandom();
	v.setRandom();

	matlabautogen::tcdf(x, v, res);

	std::cout<<x<<std::endl;
	std::cout<<v<<std::endl;
	std::cout<<res<<std::endl;

	return 0;
}


// Copyright (c) 2016-2020 The Rain Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <amount.h>
#include <policy/feerate.h>
#include <policy/policy.h>

#include <test/setup_common.h>

#include <boost/test/unit_test.hpp>

BOOST_FIXTURE_TEST_SUITE(amount_tests, BasicTestingSetup)

BOOST_AUTO_TEST_CASE(MoneyRangeTest)
{
    BOOST_CHECK_EQUAL(MoneyRange(CAmount(-1)), false);
    BOOST_CHECK_EQUAL(MoneyRange(CAmount(0)), true);
    BOOST_CHECK_EQUAL(MoneyRange(CAmount(1)), true);
    BOOST_CHECK_EQUAL(MoneyRange(MAX_MONEY), true);
    BOOST_CHECK_EQUAL(MoneyRange(MAX_MONEY + CAmount(1)), false);
}

BOOST_AUTO_TEST_CASE(GetFeeTest)
{
    CFeeRate feeRate, altFeeRate;

    feeRate = CFeeRate(CAmountMap());
    // Must always return 0
    BOOST_CHECK_EQUAL(feeRate.GetFee(0), CAmountMap());
    BOOST_CHECK_EQUAL(feeRate.GetFee(1e5), CAmountMap());
    CAmountMap map1000 = populateMap(1000);
    CAmountMap map1 = populateMap(1);
    CAmountMap map123 = populateMap(123);
    CAmountMap map2 = populateMap(2);
    CAmountMap map26 = populateMap(26);
    CAmountMap map27 = populateMap(27);
    CAmountMap map32 =populateMap(32) ;
    CAmountMap map34 = populateMap(34);
    CAmountMap mapMAX_MONEY = populateMap(MAX_MONEY);
    CAmountMap negmap1 = map1*-1;

    feeRate = CFeeRate(map1000);
    // Must always just return the arg
    BOOST_CHECK_EQUAL(feeRate.GetFee(0), populateMap(0));
    BOOST_CHECK_EQUAL(feeRate.GetFee(1), populateMap(1));
    BOOST_CHECK_EQUAL(feeRate.GetFee(121), populateMap(121));
    BOOST_CHECK_EQUAL(feeRate.GetFee(999), populateMap(999));
    BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), populateMap(1e3));
    BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), populateMap(9e3));

    feeRate = CFeeRate(map1000*-1);
    // Must always just return -1 * arg
    BOOST_CHECK_EQUAL(feeRate.GetFee(0), populateMap(0));
    BOOST_CHECK_EQUAL(feeRate.GetFee(1), populateMap(-1));
    BOOST_CHECK_EQUAL(feeRate.GetFee(121), populateMap(-121));
    BOOST_CHECK_EQUAL(feeRate.GetFee(999), populateMap(-999));
    BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), populateMap(-1e3));
    BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), populateMap(-9e3));

    feeRate = CFeeRate(map123);
    // Truncates the result, if not integer
    BOOST_CHECK_EQUAL(feeRate.GetFee(0), populateMap(0));
    BOOST_CHECK_EQUAL(feeRate.GetFee(8), populateMap(1)); // Special case: returns 1 instead of 0
    BOOST_CHECK_EQUAL(feeRate.GetFee(9), populateMap(1));
    BOOST_CHECK_EQUAL(feeRate.GetFee(121), populateMap(14));
    BOOST_CHECK_EQUAL(feeRate.GetFee(122), populateMap(15));
    BOOST_CHECK_EQUAL(feeRate.GetFee(999), populateMap(122));
    BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), populateMap(123));
    BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), populateMap(1107));

    feeRate = CFeeRate(map123*-1);
    // Truncates the result, if not integer
    BOOST_CHECK_EQUAL(feeRate.GetFee(0), populateMap(0));
    BOOST_CHECK_EQUAL(feeRate.GetFee(8), populateMap(-1)); // Special case: returns -1 instead of 0
    BOOST_CHECK_EQUAL(feeRate.GetFee(9), populateMap(-1));

    // check alternate constructor
    feeRate = CFeeRate(map1000);
    altFeeRate = CFeeRate(feeRate);
    BOOST_CHECK_EQUAL(feeRate.GetFee(100), altFeeRate.GetFee(100));

    // Check full constructor
    BOOST_CHECK(CFeeRate(negmap1, 0) == CFeeRate(CAmountMap()));
    BOOST_CHECK(CFeeRate(CAmountMap(), 0) == CFeeRate(CAmountMap()));
    BOOST_CHECK(CFeeRate(map1, 0) == CFeeRate(CAmountMap()));
    // default value

    BOOST_CHECK(CFeeRate(negmap1, 1000) == CFeeRate(negmap1));
    BOOST_CHECK(CFeeRate(CAmountMap(), 1000) == CFeeRate(CAmountMap()));
    BOOST_CHECK(CFeeRate(map1, 1000) == CFeeRate(map1));
    // lost precision (can only resolve satoshis per kB)
    BOOST_CHECK(CFeeRate(map1, 1001) == CFeeRate(CAmountMap()));
    BOOST_CHECK(CFeeRate(map2, 1001) == CFeeRate(map1));
    // some more integer checks
    BOOST_CHECK(CFeeRate(map26, 789) == CFeeRate(map32));
    BOOST_CHECK(CFeeRate(map27, 789) == CFeeRate(map34));
    // Maximum size in bytes, should not crash
    CFeeRate(mapMAX_MONEY, std::numeric_limits<size_t>::max() >> 1).GetFeePerK();
}

BOOST_AUTO_TEST_CASE(BinaryOperatorTest)
{
    CAmountMap map1 = populateMap(1);
    CAmountMap map2 = populateMap(2);

    CFeeRate a, b;
    a = CFeeRate(map1);
    b = CFeeRate(map2);
    BOOST_CHECK(a < b);
    BOOST_CHECK(b > a);
    BOOST_CHECK(a == a);
    BOOST_CHECK(a <= b);
    BOOST_CHECK(a <= a);
    BOOST_CHECK(b >= a);
    BOOST_CHECK(b >= b);
    // a should be 0.00000002 BTC/kB now
    a += a;
    BOOST_CHECK(a == b);
}

BOOST_AUTO_TEST_CASE(ToStringTest)
{
    CFeeRate feeRate;
    CAmountMap map1 = populateMap(1);

    feeRate = CFeeRate(map1);
    BOOST_CHECK_EQUAL(feeRate.ToString(), "0.00000001 BTC/kB");
}

BOOST_AUTO_TEST_SUITE_END()


#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <cctbx/geometry/geometry.h>

namespace cctbx { namespace geometry { namespace boost_python {

  static void wrap_distance() {
    using namespace boost::python;
    typedef distance<double> wt;

    class_<wt>("distance", no_init)
      .def(init<af::tiny<scitbx::vec3<double>, 2> const &>())
      .def("d_distance_d_sites", &wt::d_distance_d_sites, (
            arg("epsilon")=1.e-100))
      .def("d_distance_d_metrical_matrix", &wt::d_distance_d_metrical_matrix,
           (arg("unit_cell")))
      .def("d_distance_d_cell_params", &wt::d_distance_d_cell_params,
           (arg("unit_cell")))
      .def("variance",
       (double(wt::*)(
        af::const_ref<double, af::packed_u_accessor> const &,
        cctbx::uctbx::unit_cell const &,
        sgtbx::rt_mx const &) const)
          &wt::variance,
         (arg("covariance_matrix"),
          arg("unit_cell"),
          arg("rt_mx_ji")))
      .def("variance",
       (double(wt::*)(
        af::const_ref<double, af::packed_u_accessor> const &,
        af::const_ref<double, af::packed_u_accessor> const &,
        cctbx::uctbx::unit_cell const &,
        sgtbx::rt_mx const &) const)
          &wt::variance,
         (arg("covariance_matrix"),
          arg("cell_covariance_matrix"),
          arg("unit_cell"),
          arg("rt_mx_ji")))
      .def_readonly("distance_model", &wt::distance_model)
    ;
  }

  static void wrap_angle() {
    using namespace boost::python;
    typedef angle<double> wt;

    class_<wt>("angle", no_init)
      .def(init<af::tiny<scitbx::vec3<double>, 3> const &>())
      .def("d_angle_d_sites", &wt::d_angle_d_sites, (
            arg("epsilon")=1.e-100))
      .def("d_angle_d_metrical_matrix", &wt::d_angle_d_metrical_matrix,
           (arg("unit_cell"), arg("epsilon")=1.e-100))
      .def("d_angle_d_cell_params", &wt::d_angle_d_cell_params,
           (arg("unit_cell")))
      .def("variance",
       (double(wt::*)(
        af::const_ref<double, af::packed_u_accessor> const &,
        cctbx::uctbx::unit_cell const &,
        optional_container<af::shared<sgtbx::rt_mx> > const &) const)
          &wt::variance,
         (arg("covariance_matrix"),
          arg("unit_cell"),
          arg("sym_ops")))
      .def("variance",
       (double(wt::*)(
        af::const_ref<double, af::packed_u_accessor> const &,
        af::const_ref<double, af::packed_u_accessor> const &,
        cctbx::uctbx::unit_cell const &,
        optional_container<af::shared<sgtbx::rt_mx> > const &) const)
          &wt::variance,
         (arg("covariance_matrix"),
          arg("cell_covariance_matrix"),
          arg("unit_cell"),
          arg("sym_ops")))
      .def_readonly("angle_model", &wt::angle_model)
    ;
  }

  void init_module()
  {
    wrap_distance();
    wrap_angle();
  }

}}} // namespace cctbx::geometry::boost_python

BOOST_PYTHON_MODULE(cctbx_geometry_ext)
{
  cctbx::geometry::boost_python::init_module();
}