//==============================================================================
//         Copyright 2003 - 2012   LASMEA UMR 6602 CNRS/Univ. Clermont II
//         Copyright 2009 - 2012   LRI    UMR 8623 CNRS/Univ Paris Sud XI
//
//          Distributed under the Boost Software License, Version 1.0.
//                 See accompanying file LICENSE.txt or copy at
//                     http://www.boost.org/LICENSE_1_0.txt
//==============================================================================
#define NT2_UNIT_MODULE "nt2 trigonometric toolbox - rem_pio2/scalar Mode"

//////////////////////////////////////////////////////////////////////////////
// unit test behavior of trigonometric components in scalar mode
//////////////////////////////////////////////////////////////////////////////
/// created  by jt the 11/02/2011
///
#include <nt2/toolbox/trigonometric/include/functions/rem_pio2.hpp>
#include <nt2/toolbox/trigonometric/constants.hpp>
#include <nt2/toolbox/constant/constant.hpp>

#include <nt2/sdk/functor/meta/call.hpp>
#include <nt2/sdk/meta/scalar_of.hpp>
#include <boost/type_traits/is_same.hpp>

#include <nt2/sdk/unit/module.hpp>
#include <nt2/sdk/unit/tests/basic.hpp>
#include <nt2/sdk/unit/tests/ulp.hpp>

NT2_TEST_CASE_TPL ( rem_pio2_real__1_0,  NT2_REAL_TYPES)
{

  using nt2::rem_pio2;
  using nt2::tag::rem_pio2_;
  typedef typename nt2::meta::as_integer<T>::type iT;
  typedef typename nt2::meta::call<rem_pio2_(T)>::type r_t;
  typedef typename nt2::meta::scalar_of<r_t>::type ssr_t;
  typedef typename nt2::meta::call<rem_pio2_(T)>::type wished_r_t;

  // return type conformity test
  NT2_TEST( (boost::is_same < r_t, wished_r_t >::value) );
  std::cout << std::endl;

  // specific values tests
  typedef typename boost::fusion::result_of::value_at_c<r_t,0>::type r_t0;
  typedef typename boost::fusion::result_of::value_at_c<r_t,1>::type r_t1;
  typedef typename boost::fusion::result_of::value_at_c<r_t,2>::type r_t2;
  {
    r_t res = rem_pio2(nt2::Zero<T>());
    NT2_TEST_ULP_EQUAL( boost::fusion::get<0>(res), nt2::Zero<r_t0>(), 0.5);
    NT2_TEST_ULP_EQUAL( boost::fusion::get<1>(res), nt2::Zero<r_t1>(), 0.5);
    NT2_TEST_ULP_EQUAL( boost::fusion::get<2>(res), nt2::Zero<r_t2>(), 0.5);
  }
} // end of test for floating_

NT2_TEST_CASE_TPL ( rem_pio2_targeted,  NT2_REAL_TYPES)
{

  using nt2::rem_pio2;
  using nt2::tag::rem_pio2_;
  typedef typename nt2::meta::call<rem_pio2_(T)>::type r_t;
  typedef typename nt2::meta::scalar_of<r_t>::type ssr_t;
  typedef typename nt2::meta::call<rem_pio2_(T)>::type wished_r_t;

  nt2::uint32_t n;
  T x = nt2::Pio_2<T>(), xr, xc;
  n = rem_pio2(x, xr, xc, nt2::meta::as_<nt2::big_>());
  NT2_TEST_ULP_EQUAL( xr, nt2::Zero<T>(), 0.5);
  NT2_TEST_ULP_EQUAL( xc, nt2::Zero<T>(), 0.5);

  n = rem_pio2(x, xr, xc, nt2::meta::as_<nt2::medium_>());
  NT2_TEST_ULP_EQUAL( xr, nt2::Zero<T>(), 0.5);
  NT2_TEST_ULP_EQUAL( xc, nt2::Zero<T>(), 0.5);

  n = rem_pio2(x, xr, xc, nt2::meta::as_<nt2::small_>());
  NT2_TEST_ULP_EQUAL( xr, nt2::Zero<T>(), 0.5);
  NT2_TEST_ULP_EQUAL( xc, nt2::Zero<T>(), 0.5);

  n = rem_pio2(x, xr, xc, nt2::meta::as_<nt2::very_small_>());
  NT2_TEST_ULP_EQUAL( xr, nt2::Zero<T>(), 0.5);
  NT2_TEST_ULP_EQUAL( xc, nt2::Zero<T>(), 0.5);
}


/**
 * Copyright 2021 Scott Brauer
 *
 * 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  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.
 */

/**
 * @file   GenerateSineCandlesticksProgramOptions.hpp
 * @author Scott Brauer
 * @date   11-29-2021
 */
#ifndef OFFCENTER_TRADING_GENERATESINECANDLESTICKS_GENERATESINECANDLESTICKSPROGRAMOPTIONS__H_
#define OFFCENTER_TRADING_GENERATESINECANDLESTICKS_GENERATESINECANDLESTICKSPROGRAMOPTIONS__H_

#include <functional>
#include <iostream>
#include <sstream>

#include <boost/bind/bind.hpp>

#include "offcenter/common/program_options/ProgramOptionsGroup.hpp"
#include "offcenter/trading/generatesinecandlesticks/GenerateSineCandlesticksOptions.hpp"

namespace offcenter {
namespace trading {
namespace generatesinecandlesticks {

class GenerateSineCandlesticksProgramOptions:
		public offcenter::common::program_options::ProgramOptionsGroup<offcenter::trading::generatesinecandlesticks::GenerateSineCandlesticksOptions>
{
public:
	GenerateSineCandlesticksProgramOptions():
		ProgramOptionsGroup("Generate Sine Candlestick Options")
	{
		optionsDescription().add_options()
				("start,s", po::value<std::string>()->required()->notifier(boost::bind(&GenerateSineCandlesticksOptions::setStart, &optionConfig(), boost::placeholders::_1)), "Start time (2004-06-09T20:59:55.000000000Z)")
				("end,e", po::value<std::string>()->required()->notifier(boost::bind(&GenerateSineCandlesticksOptions::setEnd, &optionConfig(), boost::placeholders::_1)), "End time (2004-08-09T20:59:55.000000000Z)")
				("duration,d", po::value<int>(&optionConfig().m_duration)->required()->default_value(5), "Duration in seconds")

				("sine0.amplitude", po::value<double>(&optionConfig().m_sine0.m_amplitude)->required(), "Sine 0 amplitude")
				("sine0.wavelength", po::value<int>(&optionConfig().m_sine0.m_wavelength)->required(), "Sine 0 wavelength")
				("sine0.amplitude_shift", po::value<double>(&optionConfig().m_sine0.m_amplitudeShift)->required(), "Sine 0 amplitude shift")
				("sine0.wavelength_shift", po::value<int>(&optionConfig().m_sine0.m_wavelengthShift)->required(), "Sine 0 wavelength shift")

				("sine1.amplitude", po::value<double>(&optionConfig().m_sine1.m_amplitude), "Sine 1 amplitude")
				("sine1.wavelength", po::value<int>(&optionConfig().m_sine1.m_wavelength), "Sine 1 wavelength")
				("sine1.amplitude_shift", po::value<double>(&optionConfig().m_sine1.m_amplitudeShift), "Sine 1 amplitude shift")
				("sine1.wavelength_shift", po::value<int>(&optionConfig().m_sine1.m_wavelengthShift), "Sine 1 wavelength shift")

				("sine2.amplitude", po::value<double>(&optionConfig().m_sine2.m_amplitude), "Sine 2 amplitude")
				("sine2.wavelength", po::value<int>(&optionConfig().m_sine2.m_wavelength), "Sine 2 wavelength")
				("sine2.amplitude_shift", po::value<double>(&optionConfig().m_sine2.m_amplitudeShift), "Sine 2 amplitude shift")
				("sine2.wavelength_shift", po::value<int>(&optionConfig().m_sine2.m_wavelengthShift), "Sine 2 wavelength shift")

				("sine3.amplitude", po::value<double>(&optionConfig().m_sine3.m_amplitude), "Sine 3 amplitude")
				("sine3.wavelength", po::value<int>(&optionConfig().m_sine3.m_wavelength), "Sine 3 wavelength")
				("sine3.amplitude_shift", po::value<double>(&optionConfig().m_sine3.m_amplitudeShift), "Sine 3 amplitude shift")
				("sine3.wavelength_shift", po::value<int>(&optionConfig().m_sine3.m_wavelengthShift), "Sine 3 wavelength shift")

				;
	}

	virtual ~GenerateSineCandlesticksProgramOptions() = default;

	virtual void validateOptions(po::variables_map& vm) {

	}
};

} /* namespace generatesinecandlesticks */
} /* namespace trading */
} /* namespace offcenter */

#endif /* OFFCENTER_TRADING_GENERATESINECANDLESTICKS_GENERATESINECANDLESTICKSPROGRAMOPTIONS__H_ */


//==============================================================================
//         Copyright 2003 - 2011 LASMEA UMR 6602 CNRS/Univ. Clermont II
//         Copyright 2009 - 2011 LRI    UMR 8623 CNRS/Univ Paris Sud XI
//
//          Distributed under the Boost Software License, Version 1.0.
//                 See accompanying file LICENSE.txt or copy at
//                     http://www.boost.org/LICENSE_1_0.txt
//==============================================================================
#ifndef BOOST_SIMD_TOOLBOX_REDUCTION_FUNCTIONS_SIMD_COMMON_HMSB_HPP_INCLUDED
#define BOOST_SIMD_TOOLBOX_REDUCTION_FUNCTIONS_SIMD_COMMON_HMSB_HPP_INCLUDED
#include <boost/simd/toolbox/reduction/functions/hmsb.hpp>
#include <boost/simd/include/functions/simd/bits.hpp>
#include <boost/simd/sdk/meta/cardinal_of.hpp>
#include <climits>

namespace boost { namespace simd { namespace ext
{
  BOOST_SIMD_FUNCTOR_IMPLEMENTATION(boost::simd::tag::hmsb_, tag::cpu_,
                       (A0)(X),
                       ((simd_<arithmetic_<A0>,X>))
                      )
  {
    typedef size_t result_type;
    BOOST_SIMD_FUNCTOR_CALL(1)
    {
      typedef typename meta::scalar_of<A0>::type stype;

      result_type z = 0;
      const result_type N = meta::cardinal_of<A0>::value;
      for(result_type i = 0; i != N; ++i)
      {
        z |= (bits(a0[i]) >> (sizeof(stype)*CHAR_BIT - 1)) << i;
      }
      return z;
    }
  };
} } }
#endif


/*
 *                   GridGain Community Edition Licensing
 *                   Copyright 2019 GridGain Systems, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License") modified with Commons Clause
 * Restriction; 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.
 *
 * Commons Clause Restriction
 *
 * The Software is provided to you by the Licensor under the License, as defined below, subject to
 * the following condition.
 *
 * Without limiting other conditions in the License, the grant of rights under the License will not
 * include, and the License does not grant to you, the right to Sell the Software.
 * For purposes of the foregoing, “Sell” means practicing any or all of the rights granted to you
 * under the License to provide to third parties, for a fee or other consideration (including without
 * limitation fees for hosting or consulting/ support services related to the Software), a product or
 * service whose value derives, entirely or substantially, from the functionality of the Software.
 * Any license notice or attribution required by the License must also include this Commons Clause
 * License Condition notice.
 *
 * For purposes of the clause above, the “Licensor” is Copyright 2019 GridGain Systems, Inc.,
 * the “License” is the Apache License, Version 2.0, and the Software is the GridGain Community
 * Edition software provided with this notice.
 */

#ifdef _WIN32
#   include <windows.h>
#endif

#include <vector>
#include <string>

#ifndef _MSC_VER
#   define BOOST_TEST_DYN_LINK
#endif

#include <boost/test/unit_test.hpp>

#include "test_type.h"
#include "sql_test_suite_fixture.h"
#include <ignite/common/decimal.h>

using namespace ignite;

BOOST_FIXTURE_TEST_SUITE(SqlOperatorTestSuite, ignite::SqlTestSuiteFixture)

BOOST_AUTO_TEST_CASE(TestOperatorAddInt)
{
    CheckSingleResult<SQLINTEGER>("SELECT 123 + 51", 123 + 51);
};

BOOST_AUTO_TEST_CASE(TestOperatorSubInt)
{
    CheckSingleResult<SQLINTEGER>("SELECT 123 - 51", 123 - 51);
};

BOOST_AUTO_TEST_CASE(TestOperatorDivInt)
{
    CheckSingleResult<SQLINTEGER>("SELECT 123 / 51", 123 / 51);
};

BOOST_AUTO_TEST_CASE(TestOperatorModInt)
{
    CheckSingleResult<SQLINTEGER>("SELECT 123 % 51", 123 % 51);
};

BOOST_AUTO_TEST_CASE(TestOperatorMultInt)
{
    CheckSingleResult<SQLINTEGER>("SELECT 123 * 51", 123 * 51);
};

BOOST_AUTO_TEST_CASE(TestOperatorAddDouble)
{
    CheckSingleResult<double>("SELECT 123.0 + 51.0", 123.0 + 51.0);
};

BOOST_AUTO_TEST_CASE(TestOperatorSubDouble)
{
    CheckSingleResult<double>("SELECT 123.0 - 51.0", 123.0 - 51.0);
};

BOOST_AUTO_TEST_CASE(TestOperatorDivDouble)
{
    CheckSingleResult<double>("SELECT 123.0 / 51.0", 123.0 / 51.0);
};

BOOST_AUTO_TEST_CASE(TestOperatorModDouble)
{
    CheckSingleResult<double>("SELECT 123.0 % 51.0", 123 % 51);
};

BOOST_AUTO_TEST_CASE(TestOperatorMultDouble)
{
    CheckSingleResult<double>("SELECT 123.0 * 51.0", 123.0 * 51.0);
};

BOOST_AUTO_TEST_CASE(TestOperatorConcatString)
{
    CheckSingleResult<std::string>("SELECT 'Hello' || ' ' || 'World' || '!'", "Hello World!");
};

BOOST_AUTO_TEST_CASE(TestOperatorGreaterInt)
{
    CheckSingleResult<bool>("SELECT 2 > 3", false);
    CheckSingleResult<bool>("SELECT 3 > 3", false);
    CheckSingleResult<bool>("SELECT 34 > 3", true);
};

BOOST_AUTO_TEST_CASE(TestOperatorLessInt)
{
    CheckSingleResult<bool>("SELECT 4 < 4", false);
    CheckSingleResult<bool>("SELECT 4 < 4", false);
    CheckSingleResult<bool>("SELECT 8 < 42", true);
};

BOOST_AUTO_TEST_CASE(TestOperatorGreaterEquealInt)
{
    CheckSingleResult<bool>("SELECT 2 >= 3", false);
    CheckSingleResult<bool>("SELECT 3 >= 3", true);
    CheckSingleResult<bool>("SELECT 34 >= 3", true);
};

BOOST_AUTO_TEST_CASE(TestOperatorLessEquealInt)
{
    CheckSingleResult<bool>("SELECT 4 <= 3", false);
    CheckSingleResult<bool>("SELECT 4 <= 4", true);
    CheckSingleResult<bool>("SELECT 8 <= 42", true);
};

BOOST_AUTO_TEST_CASE(TestOperatorEquealInt)
{
    CheckSingleResult<bool>("SELECT 4 = 3", false);
    CheckSingleResult<bool>("SELECT 4 = 4", true);
};

BOOST_AUTO_TEST_CASE(TestOperatorNotEquealInt)
{
    CheckSingleResult<bool>("SELECT 4 != 3", true);
    CheckSingleResult<bool>("SELECT 4 != 4", false);
};

BOOST_AUTO_TEST_CASE(TestOperatorGreaterDouble)
{
    CheckSingleResult<bool>("SELECT 2 > 3", false);
    CheckSingleResult<bool>("SELECT 3 > 3", false);
    CheckSingleResult<bool>("SELECT 34 > 3", true);
};

BOOST_AUTO_TEST_CASE(TestOperatorLessDouble)
{
    CheckSingleResult<bool>("SELECT 4.0 < 4.0", false);
    CheckSingleResult<bool>("SELECT 4.0 < 4.0", false);
    CheckSingleResult<bool>("SELECT 8.0 < 42.0", true);
};

BOOST_AUTO_TEST_CASE(TestOperatorGreaterEquealDouble)
{
    CheckSingleResult<bool>("SELECT 2.0 >= 3.0", false);
    CheckSingleResult<bool>("SELECT 3.0 >= 3.0", true);
    CheckSingleResult<bool>("SELECT 34.0 >= 3.0", true);
};

BOOST_AUTO_TEST_CASE(TestOperatorLessEquealDouble)
{
    CheckSingleResult<bool>("SELECT 4.0 <= 3.0", false);
    CheckSingleResult<bool>("SELECT 4.0 <= 4.0", true);
    CheckSingleResult<bool>("SELECT 8.0 <= 42.0", true);
};

BOOST_AUTO_TEST_CASE(TestOperatorEquealDouble)
{
    CheckSingleResult<bool>("SELECT 4.0 = 3.0", false);
    CheckSingleResult<bool>("SELECT 4.0 = 4.0", true);
};

BOOST_AUTO_TEST_CASE(TestOperatorNotEquealDouble)
{
    CheckSingleResult<bool>("SELECT 4.0 != 3.0", true);
    CheckSingleResult<bool>("SELECT 4.0 != 4.0", false);
};

BOOST_AUTO_TEST_CASE(TestOperatorGreaterString)
{
    CheckSingleResult<bool>("SELECT 'abc' > 'bcd'", false);
    CheckSingleResult<bool>("SELECT 'abc' > 'abc'", false);
    CheckSingleResult<bool>("SELECT 'bcd' > 'abc'", true);
};

BOOST_AUTO_TEST_CASE(TestOperatorLessString)
{
    CheckSingleResult<bool>("SELECT 'bcd' < 'abc'", false);
    CheckSingleResult<bool>("SELECT 'abc' < 'abc'", false);
    CheckSingleResult<bool>("SELECT 'abc' < 'bcd'", true);
};

BOOST_AUTO_TEST_CASE(TestOperatorGreaterEquealString)
{
    CheckSingleResult<bool>("SELECT 'abc' >= 'bcd'", false);
    CheckSingleResult<bool>("SELECT 'abc' >= 'abc'", true);
    CheckSingleResult<bool>("SELECT 'bcd' >= 'abc'", true);
};

BOOST_AUTO_TEST_CASE(TestOperatorLessEquealString)
{
    CheckSingleResult<bool>("SELECT 'bcd' <= 'abc'", false);
    CheckSingleResult<bool>("SELECT 'abc' <= 'bcd'", true);
    CheckSingleResult<bool>("SELECT 'abc' <= 'abc'", true);
};

BOOST_AUTO_TEST_CASE(TestOperatorEquealString)
{
    CheckSingleResult<bool>("SELECT 'bcd' = 'abc'", false);
    CheckSingleResult<bool>("SELECT 'abc' = 'abc'", true);
};

BOOST_AUTO_TEST_CASE(TestOperatorNotEquealString)
{
    CheckSingleResult<bool>("SELECT 'abc' != 'abc'", false);
    CheckSingleResult<bool>("SELECT 'bcd' != 'abc'", true);
};

BOOST_AUTO_TEST_SUITE_END()


/*=========================================================================
 *
 *  Copyright David Doria 2012 daviddoria@gmail.com
 *
 *  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.txt
 *
 *  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.
 *
 *=========================================================================*/

#ifndef PatchDistanceAcceptanceVisitor_HPP
#define PatchDistanceAcceptanceVisitor_HPP

#include <boost/graph/graph_traits.hpp>

// Parent class
#include "Visitors/AcceptanceVisitors/AcceptanceVisitorParent.h"

/**

 */
template <typename TGraph>
struct PatchDistanceAcceptanceVisitor : public AcceptanceVisitorParent<TGraph>
{
  float DistanceThreshold;

  typedef typename boost::graph_traits<TGraph>::vertex_descriptor VertexDescriptorType;

  PatchDistanceAcceptanceVisitor(const float distanceThreshold = 100) :
  DistanceThreshold(distanceThreshold)
  {

  }

  bool AcceptMatch(VertexDescriptorType target, VertexDescriptorType source) const
  {
    float computedEnergy = 0.0f;
    return AcceptMatch(target, source, computedEnergy);
  }

  bool AcceptMatch(VertexDescriptorType target, VertexDescriptorType source, float& computedEnergy = 0.0f) const override
  {
    computedEnergy = sqrt(pow(target[0] - source[0], 2) + pow(target[1] - source[1], 2));

    if(computedEnergy < this->DistanceThreshold)
    {
      std::cout << "PatchDistanceAcceptanceVisitor passed with distance: " << computedEnergy << std::endl;
      return true;
    }
    std::cout << "PatchDistanceAcceptanceVisitor failed with distance: " << computedEnergy << std::endl;
    return false;
  }

};

#endif


#include <iostream>
#include <string>
#include <test/data_generator.h>
#include <test/utils.h>
#include <test/test.h>
#include <alglib/algorithms/str_matching.h>

using namespace std;

class StrMatchingTest : public Test {
    DataGenerator<string> gen;
    size_t (*func)(const string& text, const string& pattern);
  public:
    StrMatchingTest(size_t (*fn)(const string& text, const string& search));
    void run_tests();
    void run_random_tests();
    void run_custom_tests();
};

StrMatchingTest::StrMatchingTest(size_t (*fn)(const string& text, const string& search)) {
  func = fn;
}

void StrMatchingTest::run_tests() {
  run_random_tests();
  run_custom_tests();
}

void StrMatchingTest::run_random_tests() {
  const int test_cases = 100;
  const int pattern_sz = 2, search_sz = 100;

  for(int i = 0; i < test_cases; i++) {
    string pattern = gen.random_data(pattern_sz);
    string search = gen.random_data(search_sz);
    assert_(func(search, pattern) == search.find(pattern));
  }
}

void StrMatchingTest::run_custom_tests() {

}

int main() {

	StrMatchingTest routine1(naive_str_matching);
	routine1.run_tests();
	routine1.report();

  StrMatchingTest routine2(rabin_karp);
  routine2.run_tests();
  routine2.report();

  StrMatchingTest routine3(horspool);
  routine3.run_tests();
  routine3.report();

	return 0;
}


//
// Copyright © 2017 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//

#include <boost/test/unit_test.hpp>
#include "armnnTfParser/ITfParser.hpp"
#include "ParserPrototxtFixture.hpp"
#include "Runtime.hpp"
#include "Network.hpp"
#include "Graph.hpp"

BOOST_AUTO_TEST_SUITE(TensorflowParser)

// In Tensorflow fully connected layers are expressed as a MatMul followed by an Add.
// The TfParser must detect this case and convert them to a FullyConnected layer.
struct FullyConnectedFixture : public armnnUtils::ParserPrototxtFixture<armnnTfParser::ITfParser>
{
    FullyConnectedFixture()
    {
        // Input = tf.placeholder(tf.float32, [1, 1], "input")
        // Weights = tf.constant([2], tf.float32, [1, 1])
        // Matmul = tf.matmul(input, weights)
        // Bias = tf.constant([1], tf.float32)
        // Output = tf.add(matmul, bias, name="output")
        m_Prototext = R"(
node {
  name: "input"
  op: "Placeholder"
  attr {
    key: "dtype"
    value {
      type: DT_FLOAT
    }
  }
  attr {
    key: "shape"
    value {
      shape {
        dim {
          size: 1
        }
        dim {
          size: 1
        }
      }
    }
  }
}
node {
  name: "Const"
  op: "Const"
  attr {
    key: "dtype"
    value {
      type: DT_FLOAT
    }
  }
  attr {
    key: "value"
    value {
      tensor {
        dtype: DT_FLOAT
        tensor_shape {
          dim {
            size: 1
          }
          dim {
            size: 1
          }
        }
        float_val: 2.0
      }
    }
  }
}
node {
  name: "MatMul"
  op: "MatMul"
  input: "input"
  input: "Const"
  attr {
    key: "T"
    value {
      type: DT_FLOAT
    }
  }
  attr {
    key: "transpose_a"
    value {
      b: false
    }
  }
  attr {
    key: "transpose_b"
    value {
      b: false
    }
  }
}
node {
  name: "Const_1"
  op: "Const"
  attr {
    key: "dtype"
    value {
      type: DT_FLOAT
    }
  }
  attr {
    key: "value"
    value {
      tensor {
        dtype: DT_FLOAT
        tensor_shape {
          dim {
            size: 1
          }
        }
        float_val: 1.0
      }
    }
  }
}
node {
  name: "output"
  op: "Add"
  input: "MatMul"
  input: "Const_1"
  attr {
    key: "T"
    value {
      type: DT_FLOAT
    }
  }
}
        )";
        SetupSingleInputSingleOutput({ 1, 1 }, "input", "output");
    }
};

BOOST_FIXTURE_TEST_CASE(FullyConnected, FullyConnectedFixture)
{
    RunTest<1>({ 3 }, { 7 });
}

// Similar to FullyConnectedFixture, but this time the MatMul's output is used by two Adds. This should result
// in two FullyConnected layers being created.
//      I
//      |
//      M -- C
//     / \'
// C-- A  A -- C
//     \ /
//      A
struct MatMulUsedInTwoFcFixture : public armnnUtils::ParserPrototxtFixture<armnnTfParser::ITfParser>
{
    MatMulUsedInTwoFcFixture()
    {
        m_Prototext = R"(
node {
  name: "input"
  op: "Placeholder"
  attr {
    key: "dtype"
    value {
      type: DT_FLOAT
    }
  }
  attr {
    key: "shape"
    value {
      shape {
        dim {
          size: 1
        }
        dim {
          size: 1
        }
      }
    }
  }
}
node {
  name: "Const"
  op: "Const"
  attr {
    key: "dtype"
    value {
      type: DT_FLOAT
    }
  }
  attr {
    key: "value"
    value {
      tensor {
        dtype: DT_FLOAT
        tensor_shape {
          dim {
            size: 1
          }
          dim {
            size: 1
          }
        }
        float_val: 2.0
      }
    }
  }
}
node {
  name: "MatMul"
  op: "MatMul"
  input: "input"
  input: "Const"
  attr {
    key: "T"
    value {
      type: DT_FLOAT
    }
  }
  attr {
    key: "transpose_a"
    value {
      b: false
    }
  }
  attr {
    key: "transpose_b"
    value {
      b: false
    }
  }
}
node {
  name: "Const_1"
  op: "Const"
  attr {
    key: "dtype"
    value {
      type: DT_FLOAT
    }
  }
  attr {
    key: "value"
    value {
      tensor {
        dtype: DT_FLOAT
        tensor_shape {
          dim {
            size: 1
          }
        }
        float_val: 5.0
      }
    }
  }
}
node {
  name: "Const_2"
  op: "Const"
  attr {
    key: "dtype"
    value {
      type: DT_FLOAT
    }
  }
  attr {
    key: "value"
    value {
      tensor {
        dtype: DT_FLOAT
        tensor_shape {
          dim {
            size: 1
          }
        }
        float_val: 15.0
      }
    }
  }
}
node {
  name: "Add"
  op: "Add"
  input: "MatMul"
  input: "Const_1"
  attr {
    key: "T"
    value {
      type: DT_FLOAT
    }
  }
}
node {
  name: "Add_1"
  op: "Add"
  input: "MatMul"
  input: "Const_2"
  attr {
    key: "T"
    value {
      type: DT_FLOAT
    }
  }
}
node {
  name: "output"
  op: "Add"
  input: "Add"
  input: "Add_1"
  attr {
    key: "T"
    value {
      type: DT_FLOAT
    }
  }
}
        )";
        SetupSingleInputSingleOutput({ 1, 1 }, "input", "output");
    }
};

BOOST_FIXTURE_TEST_CASE(MatMulUsedInTwoFc, MatMulUsedInTwoFcFixture)
{
    RunTest<1>({ 3 }, { 32 });
    // Ideally we would check here that the armnn network has 5 layers:
    //  Input, 2 x FullyConnected (biased), Add and Output.
    // This would make sure the parser hasn't incorrectly added some unconnected layers corresponding to the MatMul.
}

// Similar to MatMulUsedInTwoFc, but this time the Adds are 'staggered' (see diagram), which means that only one
// FullyConnected layer can be created (the other should just be an Add).
//        I
//        |
//        M -- C1
//       / \'
// C2 -- A  |
//       \ /
//        A
struct MatMulUsedInTwoFcStaggeredFixture : public armnnUtils::ParserPrototxtFixture<armnnTfParser::ITfParser>
{
    MatMulUsedInTwoFcStaggeredFixture()
    {
        // Input = tf.placeholder(tf.float32, shape=[1,1], name = "input")
        // Const1 = tf.constant([17], tf.float32, [1,1])
        // Mul = tf.matmul(input, const1)
        // Monst2 = tf.constant([7], tf.float32, [1])
        // Fc = tf.add(mul, const2)
        // Output = tf.add(mul, fc, name="output")
        m_Prototext = R"(
node {
  name: "input"
  op: "Placeholder"
  attr {
    key: "dtype"
    value {
      type: DT_FLOAT
    }
  }
  attr {
    key: "shape"
    value {
      shape {
        dim {
          size: 1
        }
        dim {
          size: 1
        }
      }
    }
  }
}
node {
  name: "Const"
  op: "Const"
  attr {
    key: "dtype"
    value {
      type: DT_FLOAT
    }
  }
  attr {
    key: "value"
    value {
      tensor {
        dtype: DT_FLOAT
        tensor_shape {
          dim {
            size: 1
          }
          dim {
            size: 1
          }
        }
        float_val: 17.0
      }
    }
  }
}
node {
  name: "MatMul"
  op: "MatMul"
  input: "input"
  input: "Const"
  attr {
    key: "T"
    value {
      type: DT_FLOAT
    }
  }
  attr {
    key: "transpose_a"
    value {
      b: false
    }
  }
  attr {
    key: "transpose_b"
    value {
      b: false
    }
  }
}
node {
  name: "Const_1"
  op: "Const"
  attr {
    key: "dtype"
    value {
      type: DT_FLOAT
    }
  }
  attr {
    key: "value"
    value {
      tensor {
        dtype: DT_FLOAT
        tensor_shape {
          dim {
            size: 1
          }
        }
        float_val: 7.0
      }
    }
  }
}
node {
  name: "Add"
  op: "Add"
  input: "MatMul"
  input: "Const_1"
  attr {
    key: "T"
    value {
      type: DT_FLOAT
    }
  }
}
node {
  name: "output"
  op: "Add"
  input: "MatMul"
  input: "Add"
  attr {
    key: "T"
    value {
      type: DT_FLOAT
    }
  }
}
        )";
        SetupSingleInputSingleOutput({ 1, 1 }, "input", "output");
    }
};

BOOST_FIXTURE_TEST_CASE(MatMulUsedInTwoFcStaggered, MatMulUsedInTwoFcStaggeredFixture)
{
    RunTest<1>({ 2 }, { 75 });
    // Ideally we would check here that the armnn network has 5 layers:
    //   Input, FullyConnected (biased), FullyConnected (non biased), Add and Output.
}

// A MatMul in isolation, not connected to an add. Should result in a non-biased FullyConnected layer.
struct MatMulFixture : public armnnUtils::ParserPrototxtFixture<armnnTfParser::ITfParser>
{
    MatMulFixture()
    {
        // Input = tf.placeholder(tf.float32, shape = [1, 1], name = "input")
        // Const = tf.constant([17], tf.float32, [1, 1])
        //  Output = tf.matmul(input, const, name = "output")
        m_Prototext = R"(
node {
  name: "input"
  op: "Placeholder"
  attr {
    key: "dtype"
    value {
      type: DT_FLOAT
    }
  }
  attr {
    key: "shape"
    value {
      shape {
        dim {
          size: 1
        }
        dim {
          size: 1
        }
      }
    }
  }
}
node {
  name: "Const"
  op: "Const"
  attr {
    key: "dtype"
    value {
      type: DT_FLOAT
    }
  }
  attr {
    key: "value"
    value {
      tensor {
        dtype: DT_FLOAT
        tensor_shape {
          dim {
            size: 1
          }
          dim {
            size: 1
          }
        }
        float_val: 17.0
      }
    }
  }
}
node {
  name: "output"
  op: "MatMul"
  input: "input"
  input: "Const"
  attr {
    key: "T"
    value {
      type: DT_FLOAT
    }
  }
  attr {
    key: "transpose_a"
    value {
      b: false
    }
  }
  attr {
    key: "transpose_b"
    value {
      b: false
    }
  }
}
        )";
        SetupSingleInputSingleOutput({ 1, 1 }, "input", "output");
    }
};

BOOST_FIXTURE_TEST_CASE(MatMul, MatMulFixture)
{
    RunTest<1>({ 2 }, { 34 });
}

BOOST_AUTO_TEST_SUITE_END()


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

#ifndef NETKET_DIRECT_HAMILTONIAN_OPERATOR_HPP
#define NETKET_DIRECT_HAMILTONIAN_OPERATOR_HPP

#include <complex>
#include <vector>

#include <Eigen/Dense>

#include "Hilbert/hilbert_index.hpp"
#include "Operator/abstract_operator.hpp"
#include "abstract_matrix_wrapper.hpp"

namespace netket {

/**
 * This class wraps a given Operator. The matrix elements are not stored
 * separately but are computed from Operator::FindConn every time Apply is
 * called.
 */
template <class State = Eigen::VectorXcd>
class DirectMatrixWrapper : public AbstractMatrixWrapper<State> {
  const AbstractOperator& operator_;
  HilbertIndex hilbert_index_;
  size_t dim_;

 public:
  explicit DirectMatrixWrapper(const AbstractOperator& the_operator)
      : operator_(the_operator),
        hilbert_index_(the_operator.GetHilbert()),
        dim_(hilbert_index_.NStates()) {}

  State Apply(const State& state) const override {
    State result(dim_);
    result.setZero();

    for (size_t i = 0; i < dim_; ++i) {
      const auto v = hilbert_index_.NumberToState(i);
      operator_.ForEachConn(v, [&](ConnectorRef conn) {
        const auto j = i + hilbert_index_.DeltaStateToNumber(v, conn.positions,
                                                             conn.values);
        result(i) += conn.weight * state(j);
      });
    }
    return result;
  }

  int Dimension() const override { return dim_; }
};

}  // namespace netket

#endif  // NETKET_DIRECT_HAMILTONIAN_OPERATOR_HPP


//---------------------------------------------------------------------------//
//!
//! \file   tstDeltaDistribution.cpp
//! \author Alex Robinson
//! \brief  Delta distribution unit tests.
//!
//---------------------------------------------------------------------------//

// Std Lib Includes
#include <iostream>
#include <limits>

// Boost Includes
#include <boost/units/systems/si.hpp>
#include <boost/units/systems/cgs.hpp>
#include <boost/units/io.hpp>

// Trilinos Includes
#include <Teuchos_UnitTestHarness.hpp>
#include <Teuchos_RCP.hpp>
#include <Teuchos_ParameterList.hpp>
#include <Teuchos_XMLParameterListCoreHelpers.hpp>
#include <Teuchos_VerboseObject.hpp>

// FRENSIE Includes
#include "Utility_UnitTestHarnessExtensions.hpp"
#include "Utility_TabularOneDDistribution.hpp"
#include "Utility_DeltaDistribution.hpp"
#include "Utility_PhysicalConstants.hpp"
#include "Utility_UnitTraits.hpp"
#include "Utility_QuantityTraits.hpp"
#include "Utility_ElectronVoltUnit.hpp"

using boost::units::quantity;
using namespace Utility::Units;
namespace si = boost::units::si;
namespace cgs = boost::units::cgs;

//---------------------------------------------------------------------------//
// Testing Variables
//---------------------------------------------------------------------------//

Teuchos::RCP<Teuchos::ParameterList> test_dists_list;

Teuchos::RCP<Utility::TabularOneDDistribution>
  tab_distribution( new Utility::DeltaDistribution( 0.0 ) );

Teuchos::RCP<Utility::OneDDistribution>
  distribution( tab_distribution );

Teuchos::RCP<Utility::UnitAwareTabularOneDDistribution<si::time,si::length> >
  unit_aware_tab_distribution( new Utility::UnitAwareDeltaDistribution<si::time,si::length>( 3.0*si::seconds ) );

Teuchos::RCP<Utility::UnitAwareOneDDistribution<si::time,si::length> >
  unit_aware_distribution( unit_aware_tab_distribution );

//---------------------------------------------------------------------------//
// Tests.
//---------------------------------------------------------------------------//
// Check that the distribution can be evaluated
TEUCHOS_UNIT_TEST( DeltaDistribution, evaluate )
{
  TEST_EQUALITY_CONST( distribution->evaluate( 1.0 ), 0.0 );
  TEST_EQUALITY_CONST( distribution->evaluate( -1.0 ), 0.0 );
  TEST_EQUALITY_CONST( distribution->evaluate( 0.0 ), 1.0 );
}

//---------------------------------------------------------------------------//
// Check that the unit-aware distribution can be evaluated
TEUCHOS_UNIT_TEST( UnitAwareDeltaDistribution, evaluate )
{
  TEST_EQUALITY_CONST( unit_aware_distribution->evaluate( 0.0*si::seconds ),
		       0.0*si::meters );
  TEST_EQUALITY_CONST( unit_aware_distribution->evaluate( 3.0*si::seconds ),
		       1.0*si::meters );
  TEST_EQUALITY_CONST( unit_aware_distribution->evaluate( 6.0*si::seconds ),
		       0.0*si::meters );
}

//---------------------------------------------------------------------------//
// Check that the PDF can be evaluated
TEUCHOS_UNIT_TEST( DeltaDistribution, evaluatePDF )
{
  TEST_EQUALITY_CONST( distribution->evaluatePDF( 1.0 ), 0.0 );
  TEST_EQUALITY_CONST( distribution->evaluatePDF( -1.0 ), 0.0 );
  TEST_EQUALITY_CONST( distribution->evaluatePDF( 0.0 ), 1.0 );
}

//---------------------------------------------------------------------------//
// Check that the unit-aware PDF can be evaluated
TEUCHOS_UNIT_TEST( UnitAwareDeltaDistribution, evaluatePDF )
{
  TEST_EQUALITY_CONST( unit_aware_distribution->evaluatePDF( 0.0*si::seconds ),
		       0.0/si::seconds );
  TEST_EQUALITY_CONST( unit_aware_distribution->evaluatePDF( 3.0*si::seconds ),
		       1.0/si::seconds );
  TEST_EQUALITY_CONST( unit_aware_distribution->evaluatePDF( 6.0*si::seconds ),
		       0.0/si::seconds );
}

//---------------------------------------------------------------------------//
// Check that the CDF can be evaluated
TEUCHOS_UNIT_TEST( DeltaDistribution, evaluateCDF )
{
  TEST_EQUALITY_CONST( tab_distribution->evaluateCDF( -1.0 ), 0.0 );
  TEST_EQUALITY_CONST( tab_distribution->evaluateCDF( 0.0 ), 1.0 );
  TEST_EQUALITY_CONST( tab_distribution->evaluateCDF( 1.0 ), 1.0 );
}

//---------------------------------------------------------------------------//
// Check that the unit-aware CDF can be evaluated
TEUCHOS_UNIT_TEST( UnitAwareDeltaDistribution, evaluateCDF )
{
  TEST_EQUALITY_CONST(
		   unit_aware_tab_distribution->evaluateCDF( 0.0*si::seconds ),
		   0.0 );
  TEST_EQUALITY_CONST(
		   unit_aware_tab_distribution->evaluateCDF( 3.0*si::seconds ),
		   1.0 );
  TEST_EQUALITY_CONST(
		   unit_aware_tab_distribution->evaluateCDF( 6.0*si::seconds ),
		   1.0 );
}

//---------------------------------------------------------------------------//
// Check that the distribution can be sampled
TEUCHOS_UNIT_TEST( DeltaDistribution, sample )
{
  TEST_EQUALITY_CONST( distribution->sample(), 0.0 );
}

//---------------------------------------------------------------------------//
// Check that the unit-aware distribution can be sampled
TEUCHOS_UNIT_TEST( UnitAwareDeltaDistribution, sample )
{
  TEST_EQUALITY_CONST( unit_aware_distribution->sample(), 3.0*si::seconds );
}

//---------------------------------------------------------------------------//
// Check that the distribution can be sampled
TEUCHOS_UNIT_TEST( DeltaDistribution, sampleAndRecordTrials )
{
  unsigned trials = 0;
  double sample = distribution->sampleAndRecordTrials( trials );

  TEST_EQUALITY_CONST( sample, 0.0 );
  TEST_EQUALITY_CONST( trials, 1 );
}

//---------------------------------------------------------------------------//
// Check that the unit-aware distribution can be sampled
TEUCHOS_UNIT_TEST( UnitAwareDeltaDistribution, sampleAndRecordTrials )
{
  unsigned trials = 0;

  quantity<si::time> sample =
    unit_aware_distribution->sampleAndRecordTrials( trials );

  TEST_EQUALITY_CONST( sample, 3.0*si::seconds );
  TEST_EQUALITY_CONST( trials, 1 );
}

//---------------------------------------------------------------------------//
// Check that the distribution can be sampled
TEUCHOS_UNIT_TEST( DeltaDistribution, sampleAndRecordBinIndex )
{
  unsigned bin_index = 0;
  double sample = tab_distribution->sampleAndRecordBinIndex( bin_index );

  TEST_EQUALITY_CONST( sample, 0.0 );
  TEST_EQUALITY_CONST( bin_index, 0 );
}

//---------------------------------------------------------------------------//
// Check that the unit-aware distribution can be sampled
TEUCHOS_UNIT_TEST( UnitAwareDeltaDistribution, sampleAndRecordBinIndex )
{
  unsigned bin_index = 0;

  quantity<si::time> sample =
    unit_aware_tab_distribution->sampleAndRecordBinIndex( bin_index );

  TEST_EQUALITY_CONST( sample, 3.0*si::seconds );
  TEST_EQUALITY_CONST( bin_index, 0 );
}

//---------------------------------------------------------------------------//
// Check that the distribution can be sampled
TEUCHOS_UNIT_TEST( DeltaDistribution, sampleWithRandomNumber )
{
  double sample = tab_distribution->sampleWithRandomNumber( 0.0 );

  TEST_EQUALITY_CONST( sample, 0.0 );

  sample = tab_distribution->sampleWithRandomNumber( 0.5 );

  TEST_EQUALITY_CONST( sample, 0.0 );
}

//---------------------------------------------------------------------------//
// Check that the unit-aware distribution can be sampled
TEUCHOS_UNIT_TEST( UnitAwareDeltaDistribution, sampleWithRandomNumber )
{
  quantity<si::time> sample =
    unit_aware_tab_distribution->sampleWithRandomNumber( 0.0 );

  TEST_EQUALITY_CONST( sample, 3.0*si::seconds );

  sample = unit_aware_tab_distribution->sampleWithRandomNumber( 0.5 );

  TEST_EQUALITY_CONST( sample, 3.0*si::seconds );
}

//---------------------------------------------------------------------------//
// Check that the distribution can be sampled
TEUCHOS_UNIT_TEST( DeltaDistribution, sampleInSubrange )
{
  double sample = tab_distribution->sampleInSubrange( 1.0 );

  TEST_EQUALITY_CONST( sample, 0.0 );

  sample = tab_distribution->sampleInSubrange( 0.1 );

  TEST_EQUALITY_CONST( sample, 0.0 );
}

//---------------------------------------------------------------------------//
// Check that the unit-aware distribution can be sampled
TEUCHOS_UNIT_TEST( UnitAwareDeltaDistribution, sampleInSubrange )
{
  quantity<si::time> sample =
    unit_aware_tab_distribution->sampleInSubrange( 4.0*si::seconds );

  TEST_EQUALITY_CONST( sample, 3.0*si::seconds );

  sample = unit_aware_tab_distribution->sampleInSubrange( 3.1*si::seconds );

  TEST_EQUALITY_CONST( sample, 3.0*si::seconds );
}

//---------------------------------------------------------------------------//
// Check that the distribution can be sampled
TEUCHOS_UNIT_TEST( DeltaDistribution, sampleWithRandomNumberInSubrange )
{
  double sample =
    tab_distribution->sampleWithRandomNumberInSubrange( 0.0, 1.0 );

  TEST_EQUALITY_CONST( sample, 0.0 );

  sample = tab_distribution->sampleWithRandomNumberInSubrange( 0.5, 2.0 );

  TEST_EQUALITY_CONST( sample, 0.0 );
}

//---------------------------------------------------------------------------//
// Check that the unit-aware distribution can be sampled
TEUCHOS_UNIT_TEST( UnitAwareDeltaDistribution,
		   sampleWithRandomNumberInSubrange )
{
  quantity<si::time> sample =
    unit_aware_tab_distribution->sampleWithRandomNumberInSubrange( 0.0, 4.0*si::seconds );

  TEST_EQUALITY_CONST( sample, 3.0*si::seconds );

  sample = unit_aware_tab_distribution->sampleWithRandomNumberInSubrange( 0.5, 3.1*si::seconds );

  TEST_EQUALITY_CONST( sample, 3.0*si::seconds );
}

//---------------------------------------------------------------------------//
// Check that the upper bound of the distribution independent variable can
// be returned
TEUCHOS_UNIT_TEST( DeltaDistribution, getUpperBoundOfIndepVar )
{
  TEST_EQUALITY_CONST( distribution->getUpperBoundOfIndepVar(), 0.0 );
}

//---------------------------------------------------------------------------//
// Check that the upper bound of the unit-aware distribution independent
// variable can be returned
TEUCHOS_UNIT_TEST( UnitAwareDeltaDistribution, getUpperBoundOfIndepVar )
{
  TEST_EQUALITY_CONST( unit_aware_distribution->getUpperBoundOfIndepVar(),
		       3.0*si::seconds );
}

//---------------------------------------------------------------------------//
// Check that the lower bound of the distribution independent variable can
// be returned
TEUCHOS_UNIT_TEST( DeltaDistribution, getLowerBoundOfIndepVar )
{
  TEST_EQUALITY_CONST( distribution->getLowerBoundOfIndepVar(), 0.0 );
}

//---------------------------------------------------------------------------//
// Check that the lower bound of the unit-aware distribution independent
// variable can be returned
TEUCHOS_UNIT_TEST( UnitAwareDeltaDistribution, getLowerBoundOfIndepVar )
{
  TEST_EQUALITY_CONST( unit_aware_distribution->getLowerBoundOfIndepVar(),
		       3.0*si::seconds );
}

//---------------------------------------------------------------------------//
// Check that the distribution type can be returned
TEUCHOS_UNIT_TEST( DeltaDistribution, getDistributionType )
{
  TEST_EQUALITY_CONST( distribution->getDistributionType(),
		       Utility::DELTA_DISTRIBUTION );
}

//---------------------------------------------------------------------------//
// Check that the unit-aware distribution type can be returned
TEUCHOS_UNIT_TEST( UnitAwareDeltaDistribution, getDistributionType )
{
  TEST_EQUALITY_CONST( unit_aware_distribution->getDistributionType(),
		       Utility::DELTA_DISTRIBUTION );
}

//---------------------------------------------------------------------------//
// Check that the distribution can be written to an xml file
TEUCHOS_UNIT_TEST( DeltaDistribution, toParameterList )
{
  Teuchos::RCP<Utility::DeltaDistribution> true_distribution =
    Teuchos::rcp_dynamic_cast<Utility::DeltaDistribution>( distribution );

  Teuchos::ParameterList parameter_list;

  parameter_list.set<Utility::DeltaDistribution>( "test distribution",
						  *true_distribution );

  Teuchos::writeParameterListToXmlFile( parameter_list,
					"delta_dist_test_list.xml" );

  Teuchos::RCP<Teuchos::ParameterList> read_parameter_list =
    Teuchos::getParametersFromXmlFile( "delta_dist_test_list.xml" );

  TEST_EQUALITY( parameter_list, *read_parameter_list );

  Teuchos::RCP<Utility::DeltaDistribution>
    copy_distribution( new Utility::DeltaDistribution );

  *copy_distribution = read_parameter_list->get<Utility::DeltaDistribution>(
							  "test distribution");

  TEST_EQUALITY( *copy_distribution, *true_distribution );
}

//---------------------------------------------------------------------------//
// Check that the unit-aware distribution can be written to an xml file
TEUCHOS_UNIT_TEST( UnitAwareDeltaDistribution, toParameterList )
{
  typedef Utility::UnitAwareDeltaDistribution<si::time,si::length> UnitAwareDeltaDistribution;

  Teuchos::RCP<UnitAwareDeltaDistribution> true_distribution =
    Teuchos::rcp_dynamic_cast<UnitAwareDeltaDistribution>( unit_aware_distribution );

  Teuchos::ParameterList parameter_list;

  parameter_list.set<UnitAwareDeltaDistribution>( "test distribution",
						  *true_distribution );

  Teuchos::writeParameterListToXmlFile( parameter_list,
					"unit_aware_delta_dist_test_list.xml");

  Teuchos::RCP<Teuchos::ParameterList> read_parameter_list =
    Teuchos::getParametersFromXmlFile( "unit_aware_delta_dist_test_list.xml" );

  TEST_EQUALITY( parameter_list, *read_parameter_list );

  Teuchos::RCP<UnitAwareDeltaDistribution>
    copy_distribution( new UnitAwareDeltaDistribution );

  *copy_distribution = read_parameter_list->get<UnitAwareDeltaDistribution>(
							  "test distribution");

  TEST_EQUALITY( *copy_distribution, *true_distribution );

  std::cout << boost::units::name_string( si::energy() ) << std::endl;
}

//---------------------------------------------------------------------------//
// Check that the distribution can be read from an xml file
TEUCHOS_UNIT_TEST( DeltaDistribution, fromParameterList )
{
  Utility::DeltaDistribution xml_distribution =
    test_dists_list->get<Utility::DeltaDistribution>( "Delta Distribution A" );

  TEST_EQUALITY_CONST( xml_distribution.getLowerBoundOfIndepVar(), 0 );

  xml_distribution =
    test_dists_list->get<Utility::DeltaDistribution>( "Delta Distribution B" );

  TEST_EQUALITY_CONST( xml_distribution.getLowerBoundOfIndepVar(),
		       Utility::PhysicalConstants::pi );

  xml_distribution =
    test_dists_list->get<Utility::DeltaDistribution>( "Delta Distribution C" );

  TEST_EQUALITY_CONST( xml_distribution.getLowerBoundOfIndepVar(),
		       -Utility::PhysicalConstants::pi/2 );
}

//---------------------------------------------------------------------------//
// Check that the unit-aware distribution can be read from an xml file
TEUCHOS_UNIT_TEST( UnitAwareDeltaDistribution, fromParameterList )
{
  typedef Utility::UnitAwareDeltaDistribution<si::time,si::length> UnitAwareDeltaDistribution;

  UnitAwareDeltaDistribution xml_distribution =
    test_dists_list->get<UnitAwareDeltaDistribution>( "Unit-Aware Delta Distribution A" );

  TEST_EQUALITY_CONST( xml_distribution.getLowerBoundOfIndepVar(),
		       3.0*si::seconds );

  xml_distribution =
    test_dists_list->get<UnitAwareDeltaDistribution>( "Unit-Aware Delta Distribution B" );

  TEST_EQUALITY_CONST( xml_distribution.getLowerBoundOfIndepVar(),
		       2*Utility::PhysicalConstants::pi*si::seconds );
}

//---------------------------------------------------------------------------//
// Check that the distribution can be scaled
TEUCHOS_UNIT_TEST_TEMPLATE_4_DECL( UnitAwareDeltaDistribution,
				   explicit_conversion,
				   IndepUnitA,
				   DepUnitA,
				   IndepUnitB,
				   DepUnitB )
{
  typedef typename Utility::UnitTraits<IndepUnitA>::template GetQuantityType<double>::type IndepQuantityA;
  typedef typename Utility::UnitTraits<typename Utility::UnitTraits<IndepUnitA>::InverseUnit>::template GetQuantityType<double>::type InverseIndepQuantityA;

  typedef typename Utility::UnitTraits<IndepUnitB>::template GetQuantityType<double>::type IndepQuantityB;
  typedef typename Utility::UnitTraits<typename Utility::UnitTraits<IndepUnitB>::InverseUnit>::template GetQuantityType<double>::type InverseIndepQuantityB;

  typedef typename Utility::UnitTraits<DepUnitA>::template GetQuantityType<double>::type DepQuantityA;
  typedef typename Utility::UnitTraits<DepUnitB>::template GetQuantityType<double>::type DepQuantityB;

  // Copy from unitless distribution to distribution type A
  Utility::UnitAwareDeltaDistribution<IndepUnitA,DepUnitA>
    unit_aware_dist_a_copy = Utility::UnitAwareDeltaDistribution<IndepUnitA,DepUnitA>::fromUnitlessDistribution( *Teuchos::rcp_dynamic_cast<Utility::DeltaDistribution>( distribution ) );

  // Copy from distribution type A to distribution type B
  Utility::UnitAwareDeltaDistribution<IndepUnitB,DepUnitB>
    unit_aware_dist_b_copy( unit_aware_dist_a_copy );

  IndepQuantityA indep_quantity_a =
    Utility::QuantityTraits<IndepQuantityA>::initializeQuantity( 0.0 );
  InverseIndepQuantityA inv_indep_quantity_a =
    Utility::QuantityTraits<InverseIndepQuantityA>::initializeQuantity( 1.0 );
  DepQuantityA dep_quantity_a =
    Utility::QuantityTraits<DepQuantityA>::initializeQuantity( 1.0 );

  IndepQuantityB indep_quantity_b( indep_quantity_a );
  InverseIndepQuantityB inv_indep_quantity_b =
    Utility::QuantityTraits<InverseIndepQuantityB>::initializeQuantity( 1.0 );
  DepQuantityB dep_quantity_b( dep_quantity_a );

  UTILITY_TEST_FLOATING_EQUALITY(
			   unit_aware_dist_a_copy.evaluate( indep_quantity_a ),
			   dep_quantity_a,
			   1e-15 );
  UTILITY_TEST_FLOATING_EQUALITY(
			unit_aware_dist_a_copy.evaluatePDF( indep_quantity_a ),
			inv_indep_quantity_a,
			1e-15 );
  UTILITY_TEST_FLOATING_EQUALITY(
			   unit_aware_dist_b_copy.evaluate( indep_quantity_b ),
			   dep_quantity_b,
			   1e-15 );
  UTILITY_TEST_FLOATING_EQUALITY(
			unit_aware_dist_b_copy.evaluatePDF( indep_quantity_b ),
			inv_indep_quantity_b,
			1e-15 );

  Utility::setQuantity( indep_quantity_a, 1.0 );
  Utility::setQuantity( inv_indep_quantity_a, 0.0 );
  Utility::setQuantity( dep_quantity_a, 0.0 );

  indep_quantity_b = IndepQuantityB( indep_quantity_a );
  Utility::setQuantity( inv_indep_quantity_b, 0.0 );
  dep_quantity_b = DepQuantityB( dep_quantity_a );

  UTILITY_TEST_FLOATING_EQUALITY(
			   unit_aware_dist_a_copy.evaluate( indep_quantity_a ),
			   dep_quantity_a,
			   1e-15 );
  UTILITY_TEST_FLOATING_EQUALITY(
			unit_aware_dist_a_copy.evaluatePDF( indep_quantity_a ),
			inv_indep_quantity_a,
			1e-6 );
  UTILITY_TEST_FLOATING_EQUALITY(
			   unit_aware_dist_b_copy.evaluate( indep_quantity_b ),
			   dep_quantity_b,
			   1e-15 );
  UTILITY_TEST_FLOATING_EQUALITY(
			unit_aware_dist_b_copy.evaluatePDF( indep_quantity_b ),
			inv_indep_quantity_b,
			1e-6 );
}

typedef si::energy si_energy;
typedef cgs::energy cgs_energy;
typedef si::amount si_amount;
typedef si::length si_length;
typedef cgs::length cgs_length;
typedef si::mass si_mass;
typedef cgs::mass cgs_mass;
typedef si::dimensionless si_dimensionless;
typedef cgs::dimensionless cgs_dimensionless;

TEUCHOS_UNIT_TEST_TEMPLATE_4_INSTANT( UnitAwareDeltaDistribution,
				      explicit_conversion,
				      si_energy,
				      si_amount,
				      cgs_energy,
				      si_amount );
TEUCHOS_UNIT_TEST_TEMPLATE_4_INSTANT( UnitAwareDeltaDistribution,
				      explicit_conversion,
				      cgs_energy,
				      si_amount,
				      si_energy,
				      si_amount );
TEUCHOS_UNIT_TEST_TEMPLATE_4_INSTANT( UnitAwareDeltaDistribution,
				      explicit_conversion,
				      si_energy,
				      si_length,
				      cgs_energy,
				      cgs_length );
TEUCHOS_UNIT_TEST_TEMPLATE_4_INSTANT( UnitAwareDeltaDistribution,
				      explicit_conversion,
				      cgs_energy,
				      cgs_length,
				      si_energy,
				      si_length );
TEUCHOS_UNIT_TEST_TEMPLATE_4_INSTANT( UnitAwareDeltaDistribution,
				      explicit_conversion,
				      si_energy,
				      si_mass,
				      cgs_energy,
				      cgs_mass );
TEUCHOS_UNIT_TEST_TEMPLATE_4_INSTANT( UnitAwareDeltaDistribution,
				      explicit_conversion,
				      cgs_energy,
				      cgs_mass,
				      si_energy,
				      si_mass );
TEUCHOS_UNIT_TEST_TEMPLATE_4_INSTANT( UnitAwareDeltaDistribution,
				      explicit_conversion,
				      si_energy,
				      si_dimensionless,
				      cgs_energy,
				      cgs_dimensionless );
TEUCHOS_UNIT_TEST_TEMPLATE_4_INSTANT( UnitAwareDeltaDistribution,
				      explicit_conversion,
				      cgs_energy,
				      cgs_dimensionless,
				      si_energy,
				      si_dimensionless );
TEUCHOS_UNIT_TEST_TEMPLATE_4_INSTANT( UnitAwareDeltaDistribution,
				      explicit_conversion,
				      si_energy,
				      void,
				      cgs_energy,
				      void );
TEUCHOS_UNIT_TEST_TEMPLATE_4_INSTANT( UnitAwareDeltaDistribution,
				      explicit_conversion,
				      cgs_energy,
				      void,
				      si_energy,
				      void );
TEUCHOS_UNIT_TEST_TEMPLATE_4_INSTANT( UnitAwareDeltaDistribution,
				      explicit_conversion,
				      ElectronVolt,
				      si_amount,
				      si_energy,
				      si_amount );
TEUCHOS_UNIT_TEST_TEMPLATE_4_INSTANT( UnitAwareDeltaDistribution,
				      explicit_conversion,
				      ElectronVolt,
				      si_amount,
				      cgs_energy,
				      si_amount );
TEUCHOS_UNIT_TEST_TEMPLATE_4_INSTANT( UnitAwareDeltaDistribution,
				      explicit_conversion,
				      ElectronVolt,
				      si_amount,
				      KiloElectronVolt,
				      si_amount );
TEUCHOS_UNIT_TEST_TEMPLATE_4_INSTANT( UnitAwareDeltaDistribution,
				      explicit_conversion,
				      ElectronVolt,
				      si_amount,
				      MegaElectronVolt,
				      si_amount );
TEUCHOS_UNIT_TEST_TEMPLATE_4_INSTANT( UnitAwareDeltaDistribution,
				      explicit_conversion,
				      KiloElectronVolt,
				      si_amount,
				      si_energy,
				      si_amount );
TEUCHOS_UNIT_TEST_TEMPLATE_4_INSTANT( UnitAwareDeltaDistribution,
				      explicit_conversion,
				      KiloElectronVolt,
				      si_amount,
				      cgs_energy,
				      si_amount );
TEUCHOS_UNIT_TEST_TEMPLATE_4_INSTANT( UnitAwareDeltaDistribution,
				      explicit_conversion,
				      KiloElectronVolt,
				      si_amount,
				      ElectronVolt,
				      si_amount );
TEUCHOS_UNIT_TEST_TEMPLATE_4_INSTANT( UnitAwareDeltaDistribution,
				      explicit_conversion,
				      KiloElectronVolt,
				      si_amount,
				      MegaElectronVolt,
				      si_amount );
TEUCHOS_UNIT_TEST_TEMPLATE_4_INSTANT( UnitAwareDeltaDistribution,
				      explicit_conversion,
				      MegaElectronVolt,
				      si_amount,
				      si_energy,
				      si_amount );
TEUCHOS_UNIT_TEST_TEMPLATE_4_INSTANT( UnitAwareDeltaDistribution,
				      explicit_conversion,
				      MegaElectronVolt,
				      si_amount,
				      cgs_energy,
				      si_amount );
TEUCHOS_UNIT_TEST_TEMPLATE_4_INSTANT( UnitAwareDeltaDistribution,
				      explicit_conversion,
				      MegaElectronVolt,
				      si_amount,
				      ElectronVolt,
				      si_amount );
TEUCHOS_UNIT_TEST_TEMPLATE_4_INSTANT( UnitAwareDeltaDistribution,
				      explicit_conversion,
				      MegaElectronVolt,
				      si_amount,
				      KiloElectronVolt,
				      si_amount );
TEUCHOS_UNIT_TEST_TEMPLATE_4_INSTANT( UnitAwareDeltaDistribution,
				      explicit_conversion,
				      void,
				      MegaElectronVolt,
				      void,
				      KiloElectronVolt );

//---------------------------------------------------------------------------//
// Custom main function
//---------------------------------------------------------------------------//
int main( int argc, char** argv )
{
  std::string test_dists_xml_file;

  Teuchos::CommandLineProcessor& clp = Teuchos::UnitTestRepository::getCLP();

  clp.setOption( "test_dists_xml_file",
		 &test_dists_xml_file,
		 "Test distributions xml file name" );

  const Teuchos::RCP<Teuchos::FancyOStream> out =
    Teuchos::VerboseObjectBase::getDefaultOStream();

  Teuchos::CommandLineProcessor::EParseCommandLineReturn parse_return =
    clp.parse(argc,argv);

  if ( parse_return != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL )
  {
    *out << "\nEnd Result: TEST FAILED" << std::endl;
    return parse_return;
  }

  TEUCHOS_ADD_TYPE_CONVERTER( Utility::DeltaDistribution );
  typedef Utility::UnitAwareDeltaDistribution<si::time,si::length> UnitAwareDeltaDistribution;
  TEUCHOS_ADD_TYPE_CONVERTER( UnitAwareDeltaDistribution );

  test_dists_list = Teuchos::getParametersFromXmlFile( test_dists_xml_file );

  Teuchos::GlobalMPISession mpiSession( &argc, &argv );

  const bool success = Teuchos::UnitTestRepository::runUnitTests(*out);

  if (success)
    *out << "\nEnd Result: TEST PASSED" << std::endl;
  else
    *out << "\nEnd Result: TEST FAILED" << std::endl;

  clp.printFinalTimerSummary(out.ptr());

  return (success ? 0 : 1);
}

//---------------------------------------------------------------------------//
// end tstDeltaDistribution.cpp
//---------------------------------------------------------------------------//


//==================================================================================================
/*!

  Copyright 2016 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)
*/
//==================================================================================================
#include <boost/simd/function/scalar/saturate.hpp>
#include <scalar_test.hpp>
#include <boost/simd/detail/dispatch/meta/as_integer.hpp>
#include <boost/simd/constant/inf.hpp>
#include <boost/simd/constant/minf.hpp>
#include <boost/simd/constant/mone.hpp>
#include <boost/simd/constant/nan.hpp>
#include <boost/simd/constant/one.hpp>
#include <boost/simd/constant/zero.hpp>
#include <boost/simd/constant/valmin.hpp>
#include <boost/simd/constant/valmax.hpp>
#include <boost/simd/constant/inf.hpp>
#include <boost/simd/constant/minf.hpp>

using base = unsigned int;

STF_CASE_TPL (" saturate types check",  STF_NUMERIC_TYPES)
{
  namespace bs = boost::simd;
  using bs::saturate;
  using bs::Valmax;
  using bs::Valmin;

  // return type conformity test
  STF_EXPR_IS( saturate<T>(float(1)), float);
  STF_EXPR_IS( saturate<T>(double(1)), double);
  STF_EXPR_IS( saturate<T>(int8_t(1)), int8_t);
  STF_EXPR_IS( saturate<T>(int16_t(1)), int16_t);
  STF_EXPR_IS( saturate<T>(int32_t(1)), int32_t);
  STF_EXPR_IS( saturate<T>(int64_t(1)), int64_t);
  STF_EXPR_IS( saturate<T>(uint8_t(1)), uint8_t);
  STF_EXPR_IS( saturate<T>(uint16_t(1)), uint16_t);
  STF_EXPR_IS( saturate<T>(uint32_t(1)), uint32_t);
  STF_EXPR_IS( saturate<T>(uint64_t(1)), uint64_t);
}

STF_CASE_TPL (" saturate floating with floating",  STF_IEEE_TYPES)
{
  namespace bs = boost::simd;
  using bs::saturate;
  using bs::Valmax;
  using bs::Valmin;
  using bs::Inf;
  using bs::Minf;

  STF_EQUAL( saturate<T>(Valmax<float>()), Valmax<float>());
  STF_EQUAL( saturate<T>(Valmax<double>()), double(Valmax<T>()));
  STF_EQUAL( saturate<T>(Valmin<float>()), Valmin<float>());
  STF_EQUAL( saturate<T>(Valmin<double>()), double(Valmin<T>()));
  STF_EQUAL( saturate<T>(Inf<float>()), Inf<float>());
  STF_EQUAL( saturate<T>(Inf<double>()), double(Inf<T>()));
  STF_EQUAL( saturate<T>(Minf<float>()), Minf<float>());
  STF_EQUAL( saturate<T>(Minf<double>()), double(Minf<T>()));

}

STF_CASE_TPL (" saturate signed_int16",  (int16_t))
{
  namespace bs = boost::simd;
  using bs::saturate;
  using bs::Valmax;
  using bs::Valmin;
  // specific values tests
  STF_EQUAL(1u,           saturate<T>(1ull        ));
  STF_EQUAL(2u,           saturate<T>(2ull        ));
  STF_EQUAL(6u,           saturate<T>(6ull        ));
  STF_EQUAL(24u,          saturate<T>(24ull       ));
  STF_EQUAL(120u,         saturate<T>(120ull      ));
  STF_EQUAL(720u,         saturate<T>(720ull      ));
  STF_EQUAL(5040u,        saturate<T>(5040ull     ));
  STF_EQUAL(base(Valmax<T>()), saturate<T>(40320ull    ));
  STF_EQUAL(base(Valmax<T>()), saturate<T>(362880ull   ));
  STF_EQUAL(base(Valmax<T>()), saturate<T>(3628800ull  ));
  STF_EQUAL(base(Valmax<T>()), saturate<T>(39916800ull ));
  STF_EQUAL(base(Valmax<T>()), saturate<T>(479001600ull));
  STF_EQUAL(1,           saturate<T>(1ll        ));
  STF_EQUAL(2,           saturate<T>(2ll        ));
  STF_EQUAL(6,           saturate<T>(6ll        ));
  STF_EQUAL(24,          saturate<T>(24ll       ));
  STF_EQUAL(120,         saturate<T>(120ll      ));
  STF_EQUAL(720,         saturate<T>(720ll      ));
  STF_EQUAL(5040,        saturate<T>(5040ll     ));
  STF_EQUAL(Valmax<T>(), saturate<T>(40320ll    ));
  STF_EQUAL(Valmax<T>(), saturate<T>(362880ll   ));
  STF_EQUAL(Valmax<T>(), saturate<T>(3628800ll  ));
  STF_EQUAL(Valmax<T>(), saturate<T>(39916800ll ));
  STF_EQUAL(Valmax<T>(), saturate<T>(479001600ll));
  STF_EQUAL(-1,           saturate<T>(-1ll        ));
  STF_EQUAL(-2,           saturate<T>(-2ll        ));
  STF_EQUAL(-6,           saturate<T>(-6ll        ));
  STF_EQUAL(-24,          saturate<T>(-24ll       ));
  STF_EQUAL(-120,         saturate<T>(-120ll      ));
  STF_EQUAL(-720,         saturate<T>(-720ll      ));
  STF_EQUAL(-5040,        saturate<T>(-5040ll     ));
  STF_EQUAL(Valmin<T>(),  saturate<T>(-40320ll    ));
  STF_EQUAL(Valmin<T>(),  saturate<T>(-362880ll   ));
  STF_EQUAL(Valmin<T>(),  saturate<T>(-3628800ll  ));
  STF_EQUAL(Valmin<T>(),  saturate<T>(-39916800ll ));
  STF_EQUAL(Valmin<T>(),  saturate<T>(-479001600ll));
}

STF_CASE_TPL (" saturate unsigned_uint16",  (uint16_t))
{
  namespace bs = boost::simd;
  using bs::saturate;
  using bs::Valmax;
  using bs::Valmin;
  // specific values tests
  STF_EQUAL(1u,           saturate<T>(1ull        ));
  STF_EQUAL(2u,           saturate<T>(2ull        ));
  STF_EQUAL(6u,           saturate<T>(6ull        ));
  STF_EQUAL(24u,          saturate<T>(24ull       ));
  STF_EQUAL(120u,         saturate<T>(120ull      ));
  STF_EQUAL(720u,         saturate<T>(720ull      ));
  STF_EQUAL(5040u,        saturate<T>(5040ull     ));
  STF_EQUAL(40320u,       saturate<T>(40320ull    ));
  STF_EQUAL(base(Valmax<T>()), saturate<T>(362880ull   ));
  STF_EQUAL(base(Valmax<T>()), saturate<T>(3628800ull  ));
  STF_EQUAL(base(Valmax<T>()), saturate<T>(39916800ull ));
  STF_EQUAL(base(Valmax<T>()), saturate<T>(479001600ull));
  STF_EQUAL(1,           saturate<T>(1ll        ));
  STF_EQUAL(2,           saturate<T>(2ll        ));
  STF_EQUAL(6,           saturate<T>(6ll        ));
  STF_EQUAL(24,          saturate<T>(24ll       ));
  STF_EQUAL(120,         saturate<T>(120ll      ));
  STF_EQUAL(720,         saturate<T>(720ll      ));
  STF_EQUAL(5040,        saturate<T>(5040ll     ));
  STF_EQUAL(40320,       saturate<T>(40320ll    ));
  STF_EQUAL(Valmax<T>(), saturate<T>(362880ll   ));
  STF_EQUAL(Valmax<T>(), saturate<T>(3628800ll  ));
  STF_EQUAL(Valmax<T>(), saturate<T>(39916800ll ));
  STF_EQUAL(Valmax<T>(), saturate<T>(479001600ll));
}

STF_CASE_TPL (" saturate int8",  (int8_t))
{
  namespace bs = boost::simd;
  using bs::saturate;
  using bs::Valmax;
  using bs::Valmin;

  // specific values tests
  STF_EQUAL(1u,           saturate<T>(1ull        ));
  STF_EQUAL(2u,           saturate<T>(2ull        ));
  STF_EQUAL(6u,           saturate<T>(6ull        ));
  STF_EQUAL(24u,          saturate<T>(24ull       ));
  STF_EQUAL(120u,         saturate<T>(120ull      ));
  STF_EQUAL(base(Valmax<T>()), saturate<T>(720ull      ));
  STF_EQUAL(base(Valmax<T>()), saturate<T>(5040ull     ));
  STF_EQUAL(base(Valmax<T>()), saturate<T>(40320ull    ));
  STF_EQUAL(base(Valmax<T>()), saturate<T>(362880ull   ));
  STF_EQUAL(base(Valmax<T>()), saturate<T>(3628800ull  ));
  STF_EQUAL(base(Valmax<T>()), saturate<T>(39916800ull ));
  STF_EQUAL(base(Valmax<T>()), saturate<T>(479001600ull));
  STF_EQUAL(1,           saturate<T>(1ll        ));
  STF_EQUAL(2,           saturate<T>(2ll        ));
  STF_EQUAL(6,           saturate<T>(6ll        ));
  STF_EQUAL(24,          saturate<T>(24ll       ));
  STF_EQUAL(120,         saturate<T>(120ll      ));
  STF_EQUAL(Valmax<T>(), saturate<T>(720ll      ));
  STF_EQUAL(Valmax<T>(), saturate<T>(5040ll     ));
  STF_EQUAL(Valmax<T>(), saturate<T>(40320ll    ));
  STF_EQUAL(Valmax<T>(), saturate<T>(362880ll   ));
  STF_EQUAL(Valmax<T>(), saturate<T>(3628800ll  ));
  STF_EQUAL(Valmax<T>(), saturate<T>(39916800ll ));
  STF_EQUAL(Valmax<T>(), saturate<T>(479001600ll));
  STF_EQUAL(-1,           saturate<T>(-1ll        ));
  STF_EQUAL(-2,           saturate<T>(-2ll        ));
  STF_EQUAL(-6,           saturate<T>(-6ll        ));
  STF_EQUAL(-24,          saturate<T>(-24ll       ));
  STF_EQUAL(-120,         saturate<T>(-120ll      ));
  STF_EQUAL(Valmin<T>(),  saturate<T>(-720ll      ));
  STF_EQUAL(Valmin<T>(),  saturate<T>(-5040ll     ));
  STF_EQUAL(Valmin<T>(),  saturate<T>(-40320ll    ));
  STF_EQUAL(Valmin<T>(),  saturate<T>(-362880ll   ));
  STF_EQUAL(Valmin<T>(),  saturate<T>(-3628800ll  ));
  STF_EQUAL(Valmin<T>(),  saturate<T>(-39916800ll ));
  STF_EQUAL(Valmin<T>(),  saturate<T>(-479001600ll));
}

STF_CASE_TPL (" saturate unsigned_uint8",  (uint8_t))
{
  namespace bs = boost::simd;
  using bs::saturate;
  using bs::Valmax;
  using bs::Valmin;

  // specific values tests
  STF_EQUAL(1u,           saturate<T>(1ull        ));
  STF_EQUAL(2u,           saturate<T>(2ull        ));
  STF_EQUAL(6u,           saturate<T>(6ull        ));
  STF_EQUAL(24u,          saturate<T>(24ull       ));
  STF_EQUAL(120u,         saturate<T>(120ull      ));
  STF_EQUAL(base(Valmax<T>()), saturate<T>(720ull      ));
  STF_EQUAL(base(Valmax<T>()), saturate<T>(5040ull     ));
  STF_EQUAL(base(Valmax<T>()), saturate<T>(40320ull    ));
  STF_EQUAL(base(Valmax<T>()), saturate<T>(362880ull   ));
  STF_EQUAL(base(Valmax<T>()), saturate<T>(3628800ull  ));
  STF_EQUAL(base(Valmax<T>()), saturate<T>(39916800ull ));
  STF_EQUAL(base(Valmax<T>()), saturate<T>(479001600ull));
  STF_EQUAL(1,           saturate<T>(1ll        ));
  STF_EQUAL(2,           saturate<T>(2ll        ));
  STF_EQUAL(6,           saturate<T>(6ll        ));
  STF_EQUAL(24,          saturate<T>(24ll       ));
  STF_EQUAL(120,         saturate<T>(120ll      ));
  STF_EQUAL(Valmax<T>(), saturate<T>(720ll      ));
  STF_EQUAL(Valmax<T>(), saturate<T>(5040ll     ));
  STF_EQUAL(Valmax<T>(), saturate<T>(40320ll    ));
  STF_EQUAL(Valmax<T>(), saturate<T>(362880ll   ));
  STF_EQUAL(Valmax<T>(), saturate<T>(3628800ll  ));
  STF_EQUAL(Valmax<T>(), saturate<T>(39916800ll ));
  STF_EQUAL(Valmax<T>(), saturate<T>(479001600ll));
  STF_EQUAL(0, saturate<T>(-1ll        ));
  STF_EQUAL(0, saturate<T>(-2ll        ));
  STF_EQUAL(0, saturate<T>(-6ll        ));
  STF_EQUAL(0, saturate<T>(-24ll       ));
  STF_EQUAL(0, saturate<T>(-120ll      ));
  STF_EQUAL(0, saturate<T>(-720ll      ));
  STF_EQUAL(0, saturate<T>(-5040ll     ));
  STF_EQUAL(0, saturate<T>(-40320ll    ));
  STF_EQUAL(0, saturate<T>(-362880ll   ));
  STF_EQUAL(0, saturate<T>(-3628800ll  ));
  STF_EQUAL(0, saturate<T>(-39916800ll ));
  STF_EQUAL(0, saturate<T>(-479001600ll));
}


#include "utils/GeometryUtils.hpp"

#include <boost/test/unit_test.hpp>

using namespace utymap;
using namespace utymap::math;
using namespace utymap::utils;

BOOST_AUTO_TEST_SUITE(Utils_GeometryUtils)

BOOST_AUTO_TEST_CASE(GivenCoordinates_WhenGetCircle_ThenReturnsCorrectCircle)
{
    std::vector<GeoCoordinate> coordinates =
    {
        { 0, 0 }, { 4, 0 }, { 4, 4 }, { 0, 4 }, { 0, 0 }
    };
    GeoCoordinate center;
    double radius;

    getCircle(coordinates, center, radius);

    BOOST_CHECK_EQUAL(2, center.latitude);
    BOOST_CHECK_EQUAL(2, center.longitude);
    BOOST_CHECK_EQUAL(2, radius);
}

BOOST_AUTO_TEST_CASE(GivenRectangle_WhenGetCircle_ThenReturnsCorrectCircle)
{
    Polygon polygon(1, 0);
    polygon.addContour({ { 0, 0 }, { 4, 0 }, { 4, 4 }, { 0, 4 }, { 0, 0 }});
    Vector2 center;
    Vector2 size;

    getCircle(polygon.rectangle, center, size);

    BOOST_CHECK_EQUAL(2, center.x);
    BOOST_CHECK_EQUAL(2, center.y);
    BOOST_CHECK_EQUAL(2, size.x);
    BOOST_CHECK_EQUAL(2, size.y);
}

BOOST_AUTO_TEST_CASE(GiveSegment_WhenGetOffsetLine_ThenReturnsCorrectRectangle)
{
    std::vector<Vector2> expected = { { 0, 1 }, { 0, -1 }, { 10, -1 }, { 10, 1 } };

    auto vertices = getOffsetLine({ 0, 0 }, { 10, 0 }, 1);

    BOOST_CHECK(expected == vertices);
}

BOOST_AUTO_TEST_CASE(GivePointInPolygon_WhenIsPointInPolygon_ThenReturnsTrue)
{
    BOOST_CHECK(isPointInPolygon({ 1, 1 }, { {0, 0 }, { 0, 10 }, { 10, 10 }, { 10, 0 } }));
}

BOOST_AUTO_TEST_CASE(GivePointOnPolygonBorder_WhenIsPointInPolygon_ThenReturnsTrue)
{
    BOOST_CHECK(isPointInPolygon({ 10, 5 }, { { 0, 0 }, { 0, 10 }, { 10, 10 }, { 10, 0 } }));
}

BOOST_AUTO_TEST_CASE(GivePointIsOutsidePolygon_WhenIsPointInPolygon_ThenReturnsFalse)
{
    BOOST_CHECK(!isPointInPolygon({ 11, 11 }, { { 0, 0 }, { 0, 10 }, { 10, 10 }, { 10, 0 } }));
}

BOOST_AUTO_TEST_SUITE_END()


/*
    Copyright 2005-2007 Adobe Systems Incorporated
    Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
    or a copy at http://stlab.adobe.com/licenses.html)
*/

/*************************************************************************************************/

#ifndef ADOBE_ALGORITHM_IOTA_HPP
#define ADOBE_ALGORITHM_IOTA_HPP

#include <adobe/config.hpp>

#include <adobe/functional.hpp>

#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>

#include <algorithm>

/*************************************************************************************************/

namespace adobe {

/*************************************************************************************************/
/*!
\defgroup iota iota
\ingroup numeric

\c iota assigns sequentially increasing values to a range. That is, it assigns \c value to
\c *first, value + 1 to *(first + 1) and so on. In general, each
iterator \c i in the range [first, last) is assigned
value + (i - first).

\requirements
    - \c ForwardIterator is mutable.
    - \c T is Assignable.
    - If \c x is an object of type \c T, then \c x++ is defined.
    - \c T is convertible to ForwardIterator::value_type
    - [first, last) is a valid range.

\complexity
    - Linear. Exactly last - first assignments.
*/
/*************************************************************************************************/
/*!
    \ingroup iota

    \brief iota implementation
*/
template <class ForwardIterator, class T>
void iota (ForwardIterator first, ForwardIterator last, const T& value)
{
    std::generate(first, last, adobe::sequence_t<T>(value));
}

/*!
    \ingroup iota

    \brief iota implementation
*/
template <class ForwardRange, class T>
void iota (ForwardRange& range, const T& value)
{
    adobe::iota(boost::begin(range), boost::end(range), value);
}

/*************************************************************************************************/

} // namespace adobe

/*************************************************************************************************/

#endif

/*************************************************************************************************/


#define BOOST_TEST_MODULE lue framework core index_util
#include <hpx/config.hpp>
#include <boost/test/unit_test.hpp>
#include "lue/framework/core/index_util.hpp"

BOOST_AUTO_TEST_CASE(d2)
{
    lue::Rank const rank{2};
    using Shape = lue::Shape<lue::Count, rank>;
    using Indices = lue::Indices<lue::Index, rank>;

    {
        Shape const shape{5, 6};
        lue::Index const idx{20};

        Indices idxs = lue::linear_idx_to_idxs(idx, shape);
        BOOST_CHECK_EQUAL(idxs[0], 3);
        BOOST_CHECK_EQUAL(idxs[1], 2);
        BOOST_CHECK_EQUAL(lue::idxs_to_linear_idx(idxs, shape), idx);
    }

    {
        Shape const shape{1, 1};
        lue::Index const idx{0};

        Indices idxs = lue::linear_idx_to_idxs(idx, shape);
        BOOST_CHECK_EQUAL(idxs[0], 0);
        BOOST_CHECK_EQUAL(idxs[1], 0);
        BOOST_CHECK_EQUAL(lue::idxs_to_linear_idx(idxs, shape), idx);
    }

    {
        Shape const shape{5, 6};
        lue::Index const idx{0};

        Indices idxs = lue::linear_idx_to_idxs(idx, shape);
        BOOST_CHECK_EQUAL(idxs[0], 0);
        BOOST_CHECK_EQUAL(idxs[1], 0);
        BOOST_CHECK_EQUAL(lue::idxs_to_linear_idx(idxs, shape), idx);
    }

    {
        Shape const shape{5, 6};
        lue::Index const idx{29};

        Indices idxs = lue::linear_idx_to_idxs(idx, shape);
        BOOST_CHECK_EQUAL(idxs[0], 4);
        BOOST_CHECK_EQUAL(idxs[1], 5);
        BOOST_CHECK_EQUAL(lue::idxs_to_linear_idx(idxs, shape), idx);
    }
}


/*=============================================================================
Copyright 2020 Syed Ali Hasan <alihasan9922@gmail.com>

Distributed under the Boost Software License, Version 1.0. (See accompanying
file License.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/

#define BOOST_TEST_MODULE galactic_coord_test

#include <iostream>
#include <boost/units/io.hpp>
#include <boost/units/systems/angle/degrees.hpp>
#include <boost/astronomy/coordinate/coord_sys/galactic_coord.hpp>

#include <boost/test/unit_test.hpp>

using namespace boost::units;
using namespace boost::units::si;
using namespace boost::astronomy::coordinate;

namespace bud = boost::units::degree;

BOOST_AUTO_TEST_SUITE(galactic_coord_constructors)

BOOST_AUTO_TEST_CASE(galactic_coord_default_constructor) {
    galactic_coord<
            double,
            quantity<bud::plane_angle>,
            quantity<bud::plane_angle>>
            gc;

    //Check set_lat_lon
        gc.set_lat_lon(45.0 * bud::degrees, 18.0 * bud::degrees);

    //Check values
    BOOST_CHECK_CLOSE(gc.get_lat().value(), 45.0, 0.001);
    BOOST_CHECK_CLOSE(gc.get_lon().value(), 18.0, 0.001);

    //Quantities stored as expected?
    BOOST_TEST((std::is_same<decltype(gc.get_lat()), quantity<bud::plane_angle>>::value));
    BOOST_TEST((std::is_same<decltype(gc.get_lon()), quantity<bud::plane_angle>>::value));
}

BOOST_AUTO_TEST_CASE(galactic_coord_quantities_constructor) {
    //Make Galactic Coordinate Check
    auto gc1 = make_galactic_coord
            (15.0 * bud::degrees, 39.0 * bud::degrees);
    BOOST_CHECK_CLOSE(gc1.get_lat().value(), 15.0, 0.001);
    BOOST_CHECK_CLOSE(gc1.get_lon().value(), 39.0, 0.001);

    //Quantities stored as expected?
    BOOST_TEST((std::is_same<decltype(gc1.get_lat()), quantity<bud::plane_angle>>::value));
    BOOST_TEST((std::is_same<decltype(gc1.get_lon()), quantity<bud::plane_angle>>::value));

    //Galactic Coordinate constructor
    galactic_coord<double, quantity<bud::plane_angle>, quantity<bud::plane_angle>>
            gc2(1.5 * bud::degrees, 9.0 * bud::degrees);
    BOOST_CHECK_CLOSE(gc2.get_lat().value(), 1.5, 0.001);
    BOOST_CHECK_CLOSE(gc2.get_lon().value(), 9.0, 0.001);

    //Quantities stored as expected?
    BOOST_TEST((std::is_same<decltype(gc2.get_lat()), quantity<bud::plane_angle>>::value));
    BOOST_TEST((std::is_same<decltype(gc2.get_lon()), quantity<bud::plane_angle>>::value));
}

BOOST_AUTO_TEST_SUITE_END()


#include <iostream>
#include <memory>

#include <Eigen/Dense>
#include <boost/math/special_functions/sign.hpp>

#include <scrimmage-gtri-share/utilities/Utilities.h>
#include <scrimmage/entity/Contact.h>
#include <scrimmage/math/State.h>
#include <scrimmage/pubsub/Message.h>

#include <scrimmage/autonomy/Autonomy.h>
#include <scrimmage/plugin_manager/Plugin.h>
#include <scrimmage-gtri-share/msgs/Fire.pb.h>
#include <scrimmage/entity/Contact.h>

using Eigen::Vector2d;

namespace sc = scrimmage;

namespace scrimmage_gtri_share {

bool find_hitable(sc::StatePtr &own_state, sc::ID &own_id,
                  sc::ContactMapPtr contacts, int &hitable_id,
                  double dist_thresh, double az_thresh, double el_thresh,
                  bool use_2d)
{
    for (auto &kv : *contacts) {
        sc::Contact &cnt = kv.second;

        // Skip if own id
        if (cnt.id().id() == own_id.id()) continue;

        // Skip if on same team
        if (cnt.id().team_id() == own_id.team_id()) continue;

        // Is the enemy hitable?
        if (is_hitable(own_state, cnt.state(), dist_thresh, az_thresh,
                       el_thresh, use_2d)) {
            hitable_id = cnt.id().id();
            return true;
        }
    }
    return false;
}

bool is_hitable(sc::StatePtr &own_state, sc::StatePtr &tgt_state,
                double dist_thresh, double az_thresh, double el_thresh,
                bool use_2d)
{
    sc::State tgt = *tgt_state;
    bool fire = false;

    // Move target to same altitude if using 2D mode
    if (use_2d) {
        tgt.pos()(2) = own_state->pos()(2);
    }

    double dist = (tgt.pos() - own_state->pos()).norm();

    if (dist <= dist_thresh) {
        fire = own_state->InFieldOfView(tgt, az_thresh, el_thresh);
    }
    return fire;
}

bool publish_fire(double t, sc::PublisherPtr pub, int network_id,
                  int own_id, int tgt_id)
{
    auto msg = std::make_shared<sc::Message<Fire>>();
    msg->data.set_source_id(own_id);
    msg->data.set_target_id(tgt_id);

    msg->sender = network_id;
    msg->time = t;
    pub->publish(msg);

    return true;
}

double PropNav::update(double t, sc::State &src_state, Eigen::Vector3d &dst_pos) {

    Vector2d dst_pos2d = dst_pos.head<2>();
    Vector2d src_pos = src_state.pos().head<2>();
    Vector2d vec_to_bogy = dst_pos2d - src_pos;

    double az = atan2(vec_to_bogy(1), vec_to_bogy(0));
    double goal_ang = az;

    if (!std::isnan(last_t_) && !std::isnan(last_az_)) {
        double az_diff = sc::Angles::angle_pi(az - last_az_);
        double dt = t - last_t_;
        d_los_dt_ = az_diff / dt;
        goal_ang = src_state.quat().yaw() + (sigmoid(d_los_dt_, 0, sigmoid_w_) - 0.5) * M_PI / 2;
        goal_ang = sc::Angles::angle_pi(goal_ang);
    }
    last_az_ = az;
    last_t_ = t;
    return goal_ang;
}

double PropNav::update(double t, sc::State &src_state, sc::State &dst_state, double fire_range, double fov) {
    bool avoid;
    return update(t, src_state, dst_state, fire_range, fov, avoid);
}

double PropNav::update(double t, sc::State &src_state, sc::State &dst_state, double fire_range, double fov, bool &avoid) {

    Eigen::Vector3d pos = dst_state.pos_offset(dist_ahead_);
    double goal_ang = update(t, src_state, pos);

    Vector2d src_orient = src_state.vel().head<2>();
    Vector2d dst_pos = dst_state.pos().head<2>();
    Vector2d src_pos = src_state.pos().head<2>();
    Vector2d err = src_pos - dst_pos;

    bool src_facing_dst = err.dot(src_orient) < 0;

    if (src_facing_dst && err.norm() < fire_range && dst_state.InFieldOfView(src_state, fov, fov)) {
        avoid = true;
        double src_yaw = src_state.quat().yaw();
        if (ant_train_angle(dst_state, src_state.pos()) > 0) {
            // on right side, bank left
            goal_ang = src_yaw - M_PI / 2;
        } else {
            goal_ang = src_yaw + M_PI / 2;
        }
    } else {
        avoid = false;
    }
    return goal_ang;
}

double PointCtrl::update(double t, scrimmage::State &state, sc::State &dst_state, double fire_range, double fov, bool &avoid) {
    double goal_ang = prop_nav_.update(t, state, dst_state, fire_range, fov, avoid);
    if (std::isnan(prop_nav_.get_d_los_dt())) {
        return goal_ang;
    }
    double sign = boost::math::sign(dist_ahead_);

    dist_ahead_ +=
        gain_dlos_ * prop_nav_.get_d_los_dt() -
        sign * gain_dist_ahead_ * dist_ahead_;

    Vector2d des_pos = dst_state.pos_offset(dist_ahead_).head<2>();
    Vector2d offset = des_pos - state.pos().head<2>();
    return atan2(offset(1), offset(0));
}

} // namespace scrimmage_gtri_share