#define DEBUG 1
/**
 * File    : L.cpp
 * Author  : Kazune Takahashi
 * Created : 2020/1/31 16:50:07
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/rational.hpp>
#include <boost/multiprecision/cpp_int.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::multiprecision::cpp_int;
using ll = long long;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1000000007LL};
// constexpr ll MOD{998244353LL}; // be careful
constexpr ll MAX_SIZE{3000010LL};
// constexpr ll MAX_SIZE{30000010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
void ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
  }
}
template <typename T>
void ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
  }
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(const Mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(const Mint &a) { return *this += -a; }
  Mint &operator*=(const Mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(const Mint &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(const Mint &a) const { return Mint(*this) += a; }
  Mint operator-(const Mint &a) const { return Mint(*this) -= a; }
  Mint operator*(const Mint &a) const { return Mint(*this) *= a; }
  Mint operator/(const Mint &a) const { return Mint(*this) /= a; }
  bool operator<(const Mint &a) const { return x < a.x; }
  bool operator<=(const Mint &a) const { return x <= a.x; }
  bool operator>(const Mint &a) const { return x > a.x; }
  bool operator>=(const Mint &a) const { return x >= a.x; }
  bool operator==(const Mint &a) const { return x == a.x; }
  bool operator!=(const Mint &a) const { return !(*this == a); }
  const Mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, const Mint<MOD> &rhs)
{
  return rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator-(ll lhs, const Mint<MOD> &rhs)
{
  return -rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator*(ll lhs, const Mint<MOD> &rhs)
{
  return rhs * lhs;
}
template <ll MOD>
Mint<MOD> operator/(ll lhs, const Mint<MOD> &rhs)
{
  return Mint<MOD>{lhs} / rhs;
}
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a)
{
  return stream >> a.x;
}
template <ll MOD>
ostream &operator<<(ostream &stream, const Mint<MOD> &a)
{
  return stream << a.x;
}
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i = 2LL; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i = 1LL; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
template <typename T>
T gcd(T x, T y) { return y ? gcd(y, x % y) : x; }
template <typename T>
T lcm(T x, T y) { return x / gcd(x, y) * y; }
template <typename T>
int popcount(T x) // C++20
{
  int ans{0};
  while (x != 0)
  {
    ans += x & 1;
    x >>= 1;
  }
  return ans;
}
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1000000000000000LL};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}
// ----- main() -----

char to_char(int x)
{
  return x + 'A';
}

bool query(int const &x, int const &y)
{
  cout << "? " << to_char(x) << " " << to_char(y) << endl;
  char a;
  cin >> a;
  return a == '<';
}

template <typename Iter, typename Comp>
void merge_sort(Iter begin, Iter end, Comp cmp);

template <typename Iter, typename Comp>
void merge_sort_impl(Iter begin, Iter end, Comp cmp, random_access_iterator_tag)
{
  int N{static_cast<int>(end - begin)};
  if (N <= 1)
  {
    return;
  }
  auto mid{begin + N / 2};
  merge_sort(begin, mid, cmp);
  merge_sort(mid, end, cmp);
  vector<typename Iter::value_type> temp(N);
  merge(begin, mid, mid, end, temp.begin(), cmp);
  copy(temp.begin(), temp.end(), begin);
}

template <typename Iter, typename Comp>
void merge_sort(Iter begin, Iter end, Comp cmp)
{
  merge_sort_impl(begin, end, cmp, typename std::iterator_traits<Iter>::iterator_category());
}

bool check_vector(vector<int> const &V, int x, int y)
{
  for (auto e : V)
  {
    if (e == x)
    {
      return true;
    }
    else if (e == y)
    {
      return false;
    }
  }
  assert(false);
  return true;
}

int main()
{
  int N, Q;
  cin >> N >> Q;
  vector<int> V(N);
  for (auto i = 0; i < N; ++i)
  {
    V[i] = i;
  }
  if (Q == 1000)
  {
    sort(V.begin(), V.end(), query);
    cout << "! ";
    for (auto i = 0; i < N; ++i)
    {
      cout << to_char(V[i]);
    }
    cout << endl;
  }
  else if (Q == 100)
  {
    merge_sort(V.begin(), V.end(), query);
    cout << "! ";
    for (auto i = 0; i < N; ++i)
    {
      cout << to_char(V[i]);
    }
    cout << endl;
  }
  else
  {
    vector<vector<int>> W;
    do
    {
      W.push_back(V);
    } while (next_permutation(V.begin(), V.end()));
    while (static_cast<int>(W.size()) > 1)
    {
      auto cnt{static_cast<int>(W.size())};
      int ind_x = -1, ind_y = -1;
      for (auto x = 0; x < N; ++x)
      {
        for (auto y = x + 1; y < N; ++y)
        {
          int tmp{0};
          for (auto const &v : W)
          {
            if (check_vector(v, x, y))
            {
              ++tmp;
            }
          }
          auto c_tmp{static_cast<int>(W.size()) - tmp};
          auto t{max(tmp, c_tmp)};
          if (cnt > t)
          {
            cnt = t;
            ind_x = x;
            ind_y = y;
          }
        }
      }
      assert(ind_x != -1 && ind_y != -1);
      if (!query(ind_x, ind_y))
      {
        swap(ind_x, ind_y);
      }
      vector<vector<int>> U;
      for (auto const &v : W)
      {
        if (check_vector(v, ind_x, ind_y))
        {
          U.push_back(v);
        }
      }
      swap(U, W);
    }
    auto const &v{W[0]};
    cout << "! ";
    for (auto i = 0; i < N; ++i)
    {
      cout << to_char(v[i]);
    }
    cout << endl;
  }
}


#include "wanglandau.h"
#include <limits>
#include <iostream>
#include <fstream>
#include <boost/lexical_cast.hpp>
#include <algorithm>

namespace wanglandau{

WangLandau::WangLandau(int hsize, double flatness,
                       double final_factor, int initial_threshold,
                       double normalization, int normalization_origin)
  :hsize_(hsize), hist_(hsize), g_(hsize),
   flatness_(flatness), factor_(1.0), final_(final_factor),
   threshold_(initial_threshold), stage_(1),
   normalization_(normalization), normalization_origin_(normalization_origin)
{
}

bool WangLandau::check_flat(bool verbose = false)
{
  long hmin = std::numeric_limits<long>::max();
  int count = 0;
  long hsum = 0;
  for(int i=0; i<hsize_; ++i){
    if(hist_[i] == 0) continue;
    ++count;
    hsum += hist_[i];
    hmin = std::min(hmin, hist_[i]);
  }
  const double mean = static_cast<double>(hsum)/count;
  const double fn = hmin / mean;
  if(count < threshold_ || fn < flatness_){
    if(verbose){
      std::cout << "Histogram is not flat. "
               << "[ hmin = " << hmin
               << ", mean = " << mean
               << ", flatness = " << fn
               << ", nonzero bin = " << count
               << ", threshold = " << threshold_
               << ", factor = " << factor_
               << "]" << std::endl;
    }
    return false;
  }else{
    if(verbose){
      std::cout << "Histogram is     flat. "
               << "[ hmin = " << hmin
               << ", mean = " << mean
               << ", flatness = " << fn
               << ", nonzero bin = " << count
               << ", threshold = " << threshold_
               << ", factor = " << factor_
               << "]" << std::endl;
    }
    threshold_ = count;
    return true;
  }
}

void WangLandau::update(bool verbose=false)
{
  bool flat = check_flat(verbose);
  if(flat){

    /*
     * save and reset
     */

    std::string filename("hist-");
    filename += boost::lexical_cast<std::string>(stage_);
    filename += ".dat";
    std::ofstream ofs(filename.c_str());
    ofs << "# $1 : index" << std::endl;
    ofs << "# $2 : log of DoS" << std::endl;
    ofs << "# $3 : population" << std::endl;

    const double offset = normalization_ - g_[normalization_origin_];
    for(int i=0; i<hsize_; ++i){
      g_[i] += offset;
      if(hist_[i] != 0)
        ofs << i << " " << g_[i] << " " << hist_[i] << std::endl;
      hist_[i] = 0;
    }

    std::cout << "# " <<  stage_ << " iteration (factor = " << factor_ << " ) finished." << std::endl;
    factor_ *= 0.5;
    ++stage_;
  }
}

} // end of namespace wanglandau


#include "stdafx.h"

#include "problem.hpp"

#include <fstream>
#include <vector>
#include <unordered_map>
#include <boost/algorithm/string.hpp>

struct advent_2017_11 : problem
{
	advent_2017_11() noexcept : problem(2017, 11) {
	}

protected:
	enum struct compass
	{
		n,
		ne,
		se,
		s,
		sw,
		nw,
	};

	compass str_to_direction(const std::string& str) {
		if(str == "n") {
			return compass::n;
		} else if(str == "ne") {
			return compass::ne;
		} else if(str == "se") {
			return compass::se;
		} else if(str == "s") {
			return compass::s;
		} else if(str == "sw") {
			return compass::sw;
		} else if(str == "nw") {
			return compass::nw;
		} else {
			__assume(0);
		}
	}

	std::vector<compass> directions;

	void prepare_input(std::ifstream& fin) override {
		std::string line;
		std::getline(fin, line);
		std::vector<std::string> raw_directions;
		boost::split(raw_directions, line, [](char c) { return c == ','; });
		std::transform(std::begin(raw_directions), std::end(raw_directions), std::back_inserter(directions), [&](const std::string& str) {
			return str_to_direction(str);
		});
	}

	std::size_t greatest_distance = 0;
	std::size_t current_distance = 0;

	struct hex_coord
	{
		std::ptrdiff_t x, y, z;

		hex_coord& operator+=(compass d) noexcept {
			switch(d) {
			case compass::n:      ++y; --z; break;
			case compass::ne: ++x;      --z; break;
			case compass::se: ++x; --y;      break;
			case compass::s:      --y; ++z; break;
			case compass::sw: --x;      ++z; break;
			case compass::nw: --x; ++y;      break;
			}
			return *this;
		}
	};

	std::size_t distance_from_origin(hex_coord c) {
		return gsl::narrow<std::size_t>((std::abs(c.x) + std::abs(c.y) + std::abs(c.z)) / 2);
	}

	void precompute() override {
		hex_coord position{ 0, 0, 0 };
		std::for_each(std::begin(directions), std::end(directions), [&](compass d) {
			position += d;
			current_distance = distance_from_origin(position);
			greatest_distance = std::max(greatest_distance, current_distance);
		});
	}

	std::string part_1() override {
		return std::to_string(current_distance);
	}

	std::string part_2() override {
		return std::to_string(greatest_distance);
	}
};

REGISTER_SOLVER(2017, 11);


/* ---------------------------------------------------------------------
 *
 * Copyright (C) 1999 - 2021 by the deal.II authors
 *
 * This file is part of the deal.II library.
 *
 * The deal.II library is free software; you can use it, redistribute
 * it, and/or modify it under the terms of the GNU Lesser General
 * Public License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * The full text of the license can be found in the file LICENSE.md at
 * the top level directory of deal.II.
 *
 * ---------------------------------------------------------------------
 *
 * Author: Wolfgang Bangerth, University of Heidelberg, 1999
 */

// @sect3{Include files}

// 前面几个（很多）include文件已经在前面的例子中使用过了，所以我们在这里不再解释它们的含义。

#include <deal.II/grid/tria.h>
#include <deal.II/dofs/dof_handler.h>
#include <deal.II/grid/grid_generator.h>
#include <deal.II/fe/fe_q.h>
#include <deal.II/dofs/dof_tools.h>
#include <deal.II/fe/fe_values.h>
#include <deal.II/base/quadrature_lib.h>
#include <deal.II/base/function.h>
#include <deal.II/numerics/vector_tools.h>
#include <deal.II/numerics/matrix_tools.h>
#include <deal.II/lac/vector.h>
#include <deal.II/lac/full_matrix.h>
#include <deal.II/lac/sparse_matrix.h>
#include <deal.II/lac/dynamic_sparsity_pattern.h>
#include <deal.II/lac/solver_cg.h>
#include <deal.II/lac/precondition.h>

#include <deal.II/numerics/data_out.h>
#include <fstream>
#include <iostream>

// 这是新的，但是：在前面的例子中，我们从线性求解器得到了一些不需要的输出。如果我们想抑制它，我们必须包括这个文件，并在程序的某个地方添加一行字（见下面的main()函数）。

#include <deal.II/base/logstream.h>

// 最后一步，和以前的程序一样，是将所有deal.II的类和函数名导入全局命名空间中。

using namespace dealii;
// @sect3{The Step4 class template}

// 这又是前面例子中的 Step4 类。唯一不同的是，我们现在把它声明为一个带有模板参数的类，而模板参数当然是我们要解决拉普拉斯方程的空间维度。当然，几个成员变量也取决于这个维度，特别是Triangulation类，它必须分别表示四边形或六面体。除此以外，一切都和以前一样。

template <int dim>
class Step4
{
public:
  Step4();
  void run();

private:
  void make_grid();
  void setup_system();
  void assemble_system();
  void solve();
  void output_results() const;

  Triangulation<dim> triangulation;
  FE_Q<dim>          fe;
  DoFHandler<dim>    dof_handler;

  SparsityPattern      sparsity_pattern;
  SparseMatrix<double> system_matrix;

  Vector<double> solution;
  Vector<double> system_rhs;
};
// @sect3{Right hand side and boundary values}

// 在下文中，我们又声明了两个类，表示右手边和非均质的Dirichlet边界值。两者都是一个二维空间变量的函数，所以我们也将它们声明为模板。

// 这些类中的每一个都是从一个共同的、抽象的基类Function派生出来的，它声明了所有函数都必须遵循的共同接口。特别是，具体的类必须重载 value 函数，该函数接收二维空间中的一个点作为参数，并将该点的值作为 double 变量返回。

//  value 函数需要第二个参数，我们在这里将其命名为 component  : 这只适用于矢量值函数，你可能想访问点 p 处的矢量的某个分量。然而，我们的函数是标量的，所以我们不需要担心这个参数，在函数的实现中也不会使用它。在库的头文件中，Function基类对 value 函数的声明中，分量的默认值为0，所以我们在访问右侧的 value 函数时，只需要一个参数，即我们要评估函数的点。然后，对于标量函数，可以简单地省略分量的值。

// 函数对象在库中很多地方都有使用（例如，在 step-3 中我们使用了一个 Functions::ZeroFunction 实例作为 VectorTools::interpolate_boundary_values) 的参数，这是我们定义一个继承自Function的新类的第一个教程。由于我们只调用 Function::value(), ，我们可以只用一个普通的函数（这就是 step-5 中的做法），但由于这是一个教程，为了举例说明，我们继承了Function。

template <int dim>
class RightHandSide : public Function<dim>
{
public:
  virtual double value(const Point<dim> & p,
                       const unsigned int component = 0) const override;
};

template <int dim>
class BoundaryValues : public Function<dim>
{
public:
  virtual double value(const Point<dim> & p,
                       const unsigned int component = 0) const override;
};

// 如果你不熟悉上述函数声明中的关键字 "virtual "和 "override "是什么意思，你可能会想看看你最喜欢的C++书籍或在线教程，如http:www.cplusplus.com/doc/tutorial/polymorphism/ 。从本质上讲，这里发生的事情是Function<dim>是一个 "抽象 "基类，它声明了某种 "接口"--一组可以在这类对象上调用的函数。但它实际上并没有*实现*这些函数：它只是说 "Function对象是这样的"，但它实际上是什么样的函数，则留给实现了`value()`函数的派生类。

// 从另一个类中派生出一个类，通常称为 "is-a "关系函数。在这里，`RightHandSide`类 "是一个 "函数类，因为它实现了Function基类所描述的接口。("value() "函数的实际实现在下面的代码块中)。那么`virtual`关键字意味着 "是的，这里的函数可以被派生类覆盖"，而`override`关键字意味着 "是的，这实际上是一个我们知道已经被声明为基类一部分的函数"。覆盖 "关键字不是严格必要的，但它是防止打字错误的一个保险。如果我们把函数的名字或一个参数的类型弄错了，编译器会警告我们说："你说这个函数覆盖了基类中的一个函数，但实际上我不知道有任何这样的函数有这个名字和这些参数。"

// 但回到这里的具体案例。在本教程中，我们选择2D中的函数 $4(x^4+y^4)$ ，或者3D中的 $4(x^4+y^4+z^4)$ 作为右手边。我们可以用空间维度上的if语句来写这个区别，但这里有一个简单的方法，通过使用一个短循环，也允许我们在一维（或四维，如果你想这样做）中使用相同的函数。 幸运的是，编译器在编译时就知道循环的大小（记住，在你定义模板时，编译器不知道 dim 的值，但当它后来遇到语句或声明 RightHandSide@<2@> 时，它将采取模板，用2替换所有出现的dim，并编译出结果函数）。 换句话说，在编译这个函数的时候，主体将被执行的次数是已知的，编译器可以将循环所需的开销降到最低；结果将和我们马上使用上面的公式一样快。

// 最后要注意的是， Point@<dim@> 表示二维空间中的一个点，它的各个组成部分（即 $x$ 、 $y$ 、...坐标）可以像C和C++中一样用（）运算符访问（事实上，[]运算符也同样有效），索引从0开始。

template <int dim>
double RightHandSide<dim>::value(const Point<dim> &p,
                                 const unsigned int /*component*/) const
{
  double return_value = 0.0;
  for (unsigned int i = 0; i < dim; ++i)
    return_value += 4.0 * std::pow(p(i), 4.0);

  return return_value;
}

// 作为边界值，我们选择二维的 $x^2+y^2$ ，三维的 $x^2+y^2+z^2$ 。这恰好等于从原点到我们想评估函数的点的矢量的平方，而不考虑维度。所以这就是我们的返回值。

template <int dim>
double BoundaryValues<dim>::value(const Point<dim> &p,
                                  const unsigned int /*component*/) const
{
  return p.square();
}

//  @sect3{Implementation of the Step4 class}

// 接下来是利用上述函数的类模板的实现。和以前一样，我们将把所有东西写成模板，这些模板有一个形式参数 dim ，在我们定义模板函数时，我们假设这个参数是未知的。只有在以后，编译器才会发现 Step4@<2@> (in the main 函数的声明，实际上），并在编译整个类时将 dim 替换成2，这个过程被称为 "模板的实例化"。这样做的时候，它也会用 RightHandSide@<dim@> 的实例替换 RightHandSide@<2@> ，并从类模板中实例化后一个类。

// 事实上，编译器也会在 main() 中找到一个 Step4@<3@> 声明。这将导致它再次回到一般的 Step4@<dim@> 模板，替换所有出现的 dim ，这次是3，并第二次编译这个类。注意这两个实例  Step4@<2@>  和  Step4@<3@>  是完全独立的类；它们唯一的共同特征是它们都是从同一个通用模板中实例化出来的，但是它们不能相互转换，例如，它们没有共享代码（两个实例都是完全独立编译的）。

//  @sect4{Step4::Step4}

// 在这个介绍之后，这里是  Step4  类的构造函数。它指定了所需的有限元素的多项式程度，并将DoFHandler与三角形关联起来，就像在前面的例子程序中一样，  step-3  。

template <int dim>
Step4<dim>::Step4()
  : fe(1)
  , dof_handler(triangulation)
{}
// @sect4{Step4::make_grid}

// 网格的创建在本质上是与维度有关的东西。然而，只要领域在二维或三维中足够相似，库就可以为你抽象。在我们的例子中，我们想再次在二维的正方形 $[-1,1]\times [-1,1]$ 上求解，或者在三维的立方体 $[-1,1] \times [-1,1] \times [-1,1]$ 上求解；两者都可以被称为 GridGenerator::hyper_cube(), ，因此我们可以在任何维度上使用同一个函数。当然，在二维和三维中创建超立方体的函数有很大的不同，但这是你不需要关心的事情。让库来处理这些困难的事情。

template <int dim>
void Step4<dim>::make_grid()
{
  GridGenerator::hyper_cube(triangulation, -1, 1);
  triangulation.refine_global(4);

  std::cout << "   Number of active cells: " << triangulation.n_active_cells()
            << std::endl
            << "   Total number of cells: " << triangulation.n_cells()
            << std::endl;
}
// @sect4{Step4::setup_system}

// 这个函数看起来和前面的例子完全一样，尽管它执行的动作在细节上有很大的不同，如果 dim 刚好是3。从用户的角度来看，唯一显著的区别是所产生的单元格数量，在三个空间维度中比两个空间维度中要高得多

template <int dim>
void Step4<dim>::setup_system()
{
  dof_handler.distribute_dofs(fe);

  std::cout << "   Number of degrees of freedom: " << dof_handler.n_dofs()
            << std::endl;

  DynamicSparsityPattern dsp(dof_handler.n_dofs());
  DoFTools::make_sparsity_pattern(dof_handler, dsp);
  sparsity_pattern.copy_from(dsp);

  system_matrix.reinit(sparsity_pattern);

  solution.reinit(dof_handler.n_dofs());
  system_rhs.reinit(dof_handler.n_dofs());
}
// @sect4{Step4::assemble_system}

// 与前面的例子不同，我们现在想使用一个非恒定的右侧函数和非零边界值。这两个任务都是很容易实现的，只需在矩阵和右手边的组合中增加几行代码即可。

// 更有趣的是，我们将矩阵和右手边的向量维度独立组装起来的方式：与二维的情况根本没有区别。由于这个函数中使用的重要对象（正交公式、FEValues）也通过模板参数的方式依赖于维度，它们可以为这个函数所编译的维度正确设置一切。通过使用模板参数声明所有可能依赖于维度的类，库可以为你完成几乎所有的工作，你不需要关心大多数事情。

template <int dim>
void Step4<dim>::assemble_system()
{
  QGauss<dim> quadrature_formula(fe.degree + 1);

// 我们希望有一个非恒定的右手，所以我们使用上面声明的类的一个对象来生成必要的数据。由于这个右侧对象只在本函数中局部使用，所以我们在这里把它声明为一个局部变量。

  RightHandSide<dim> right_hand_side;

// 与之前的例子相比，为了评估非恒定右手函数，我们现在还需要我们目前所在单元上的正交点（之前，我们只需要FEValues对象中的形状函数的值和梯度，以及正交权重， FEValues::JxW() ）。我们可以通过给FEValues对象添加#update_quadrature_points标志来让它为我们做事。

  FEValues<dim> fe_values(fe,
                          quadrature_formula,
                          update_values | update_gradients |
                            update_quadrature_points | update_JxW_values);

// 然后我们再次定义与前面程序中相同的缩写。这个变量的值当然取决于我们现在使用的维度，但是FiniteElement类为你做了所有必要的工作，你不需要关心与维度有关的部分。

  const unsigned int dofs_per_cell = fe.n_dofs_per_cell();

  FullMatrix<double> cell_matrix(dofs_per_cell, dofs_per_cell);
  Vector<double>     cell_rhs(dofs_per_cell);

  std::vector<types::global_dof_index> local_dof_indices(dofs_per_cell);

// 接下来，我们又要在所有的单元格上进行循环，并汇集局部贡献。 请注意，一个单元在两个空间维度上是一个四边形，但在三维上是一个六面体。事实上， active_cell_iterator 的数据类型是不同的，这取决于我们所处的维度，但对外界来说，它们看起来是一样的，你可能永远不会看到区别。在任何情况下，真正的类型是通过使用`auto`来隐藏的。

  for (const auto &cell : dof_handler.active_cell_iterators())
    {
      fe_values.reinit(cell);
      cell_matrix = 0;
      cell_rhs    = 0;

// 现在我们要把本地矩阵和右手边组合起来。这个过程和前面的例子完全一样，但是现在我们重新调整循环的顺序（我们可以安全地这样做，因为它们是相互独立的），并尽可能地合并本地矩阵和本地向量的循环，使事情变得更快。

// 组装右手边与我们在 step-3 中的做法有唯一的区别：我们没有使用值为1的常数右手边，而是使用代表右手边的对象并在正交点对其进行评估。

      for (const unsigned int q_index : fe_values.quadrature_point_indices())
        for (const unsigned int i : fe_values.dof_indices())
          {
            for (const unsigned int j : fe_values.dof_indices())
              cell_matrix(i, j) +=
                (fe_values.shape_grad(i, q_index) * // grad phi_i(x_q)
                 fe_values.shape_grad(j, q_index) * // grad phi_j(x_q)
                 fe_values.JxW(q_index));           // dx

            const auto &x_q = fe_values.quadrature_point(q_index);
            cell_rhs(i) += (fe_values.shape_value(i, q_index) * // phi_i(x_q)
                            right_hand_side.value(x_q) *        // f(x_q)
                            fe_values.JxW(q_index));            // dx
          }

// 作为对这些循环的最后说明：当我们将局部贡献集合到 cell_matrix(i,j) 时，我们必须将形状函数 $i$ 和 $j$ 在点号q_index的梯度相乘并与标量权重JxW相乘。这就是实际发生的情况。  fe_values.shape_grad(i,q_index) 返回一个 dim 维向量，由 Tensor@<1,dim@> 对象表示，将其与 fe_values.shape_grad(j,q_index) 的结果相乘的运算器*确保两个向量的 dim 分量被适当收缩，结果是一个标量浮点数，然后与权重相乘。在内部，这个操作符*确保对向量的所有 dim 分量都能正确发生，无论 dim 是2、3还是其他空间维度；从用户的角度来看，这并不值得费心，然而，如果想独立编写代码维度，事情就会简单很多。

// 随着本地系统的组装，转移到全局矩阵和右手边的工作与之前完全一样，但在这里我们再次合并了一些循环以提高效率。

      cell->get_dof_indices(local_dof_indices);
      for (const unsigned int i : fe_values.dof_indices())
        {
          for (const unsigned int j : fe_values.dof_indices())
            system_matrix.add(local_dof_indices[i],
                              local_dof_indices[j],
                              cell_matrix(i, j));

          system_rhs(local_dof_indices[i]) += cell_rhs(i);
        }
    }

// 作为这个函数的最后一步，我们希望在这个例子中拥有非均质的边界值，与之前的例子不同。这是一个简单的任务，我们只需要用一个描述我们想使用的边界值的类的对象（即上面声明的 BoundaryValues 类）来替换那里使用的 Functions::ZeroFunction 。

// 函数 VectorTools::interpolate_boundary_values() 只对标有边界指标0的面起作用（因为我们在下面的第二个参数中说该函数应该对其起作用）。如果有的面的边界指标不是0，那么函数interpolate_boundary_values将对这些面不起作用。对于拉普拉斯方程来说，什么都不做相当于假设在边界的这些部分，零诺伊曼边界条件成立。

  std::map<types::global_dof_index, double> boundary_values;
  VectorTools::interpolate_boundary_values(dof_handler,
                                           0,
                                           BoundaryValues<dim>(),
                                           boundary_values);
  MatrixTools::apply_boundary_values(boundary_values,
                                     system_matrix,
                                     solution,
                                     system_rhs);
}
// @sect4{Step4::solve}

// 解决线性方程组是在大多数程序中看起来几乎相同的事情。特别是，它与维度无关，所以这个函数是从前面的例子中逐字复制的。

template <int dim>
void Step4<dim>::solve()
{
  SolverControl            solver_control(1000, 1e-12);
  SolverCG<Vector<double>> solver(solver_control);
  solver.solve(system_matrix, solution, system_rhs, PreconditionIdentity());

// 不过我们做了一个补充：由于我们抑制了线性求解器的输出，我们必须手工打印迭代次数。

  std::cout << "   " << solver_control.last_step()
            << " CG iterations needed to obtain convergence." << std::endl;
}
// @sect4{Step4::output_results}

// 这个函数也做了  step-3  中各自的工作。这里也没有改变维度的独立性。

// 由于程序将同时运行拉普拉斯求解器的2D和3D版本，我们使用文件名中的维度为每次运行生成不同的文件名（在一个更好的程序中，我们将检查 dim 是否可以有2或3以外的其他值，但为了简洁起见，我们在这里忽略了这一点）。

template <int dim>
void Step4<dim>::output_results() const
{
  DataOut<dim> data_out;

  data_out.attach_dof_handler(dof_handler);
  data_out.add_data_vector(solution, "solution");

  data_out.build_patches();

  std::ofstream output(dim == 2 ? "solution-2d.vtk" : "solution-3d.vtk");
  data_out.write_vtk(output);
}

//  @sect4{Step4::run}

// 这是一个对所有事情都有最高级别控制的函数。除了一行额外的输出外，它与前面的例子相同。

template <int dim>
void Step4<dim>::run()
{
  std::cout << "Solving problem in " << dim << " space dimensions."
            << std::endl;

  make_grid();
  setup_system();
  assemble_system();
  solve();
  output_results();
}
// @sect3{The main function}

// 这是主函数。它看起来也大多像 step-3 中的内容，但如果你看下面的代码，注意我们是如何首先创建一个 Step4@<2@> 类型的变量（迫使编译器用 dim replaced by 2 编译类模板）并运行一个2d模拟，然后我们用3d做整个事情。

// 在实践中，这可能不是你经常做的事情（你可能要么想解决一个2D的问题，要么想解决一个3D的问题，但不会同时解决这两个问题）。然而，它展示了一种机制，我们可以在一个地方简单地改变我们想要的维度，从而迫使编译器为我们要求的维度重新编译独立的类模板。这里的重点在于，我们只需要改变一个地方。这使得在计算速度较快的2D环境下调试程序变得非常简单，然后将一个地方切换到3，在3D环境下运行计算量大得多的程序，进行 "真实 "的计算。

// 这两个区块中的每一个都用大括号括起来，以确保 laplace_problem_2d 这个变量在我们继续为3D情况分配内存之前就已经超出了范围（并释放了它所持有的内存）。如果没有额外的大括号， laplace_problem_2d 变量只会在函数结束时被销毁，也就是在运行完3d问题后被销毁，而且会在3d运行时不必要地占用内存，而实际使用它。

int main()
{
  {
    Step4<2> laplace_problem_2d;
    laplace_problem_2d.run();
  }

  {
    Step4<3> laplace_problem_3d;
    laplace_problem_3d.run();
  }

  return 0;
}


#include <boost/math/special_functions/factorials.hpp>
#include "gauss_distribution.hpp"

namespace bayesopt
{

  GaussianDistribution::GaussianDistribution(randEngine& eng):
    ProbabilityDistribution(eng)
  {
    mean_ = 0.0;  std_ = 1.0;
  }

  GaussianDistribution::~GaussianDistribution(){}

  double GaussianDistribution::negativeExpectedImprovement(double min,
							   size_t g)
  {

    using boost::math::factorial;

    const double diff = min - mean_;
    const double z = diff / std_;
    const double pdf_z = boost::math::pdf(d_,z);
    const double cdf_z = boost::math::cdf(d_,z);

    if (g == 1)
      return -1.0 * ( diff * cdf_z + std_ * pdf_z );
    else
      {
	const double fg = factorial<double>(g);

	double Tm2 = cdf_z;
	double Tm1 = pdf_z;
	double sumEI = pow(z,static_cast<double>(g))*Tm2 - g*pow(z,static_cast<double>(g-1))*Tm1;

	for (size_t ii = 2; ii < g; ++ii)
	  {
	    double Tact = (ii-1)*Tm2 - pdf_z*pow(z,static_cast<double>(ii-1));
	    sumEI += pow(-1.0,static_cast<double>(ii))*
	      (fg / ( factorial<double>(ii)*factorial<double>(g-ii) ) )*
	      pow(z,static_cast<double>(g-ii))*Tact;

	    //roll-up
	    Tm2 = Tm1;   Tm1 = Tact;
	  }
	return -1.0 * pow(std_,static_cast<double>(g)) * sumEI;
      }

  }  // negativeExpectedImprovement

  double GaussianDistribution::lowerConfidenceBound(double beta)
  {
    return mean_ - beta*std_;
  }  // lowerConfidenceBound

  double GaussianDistribution::negativeProbabilityOfImprovement(double min,
								double epsilon)
  {
    return -cdf(d_,(min - mean_ + epsilon)/std_);
  }  // negativeProbabilityOfImprovement

  double GaussianDistribution::sample_query()
  {
    randNFloat sample(mtRandom,normalDist(mean_,std_));
    return sample();
  } // sample_query

}


#include <iostream>
#include <array>
#include <vector>
#include <fstream>
#include <cmath>
#include <iterator>

#include <boost/iterator/transform_iterator.hpp>
#include <boost/iterator/function_input_iterator.hpp>
#include <boost/log/trivial.hpp>

#include <range/v3/algorithm.hpp>

#include "maikel/hmm/hidden_markov_model.h"
#include "maikel/hmm/algorithm.h"
#include "maikel/hmm/io.h"
#include "maikel/function_profiler.h"

enum Exit_Error_Codes {
  exit_success = 0,
  exit_not_enough_arguments = 1,
  exit_io_error = 2,
  exit_argument_error = 3
};

template <class float_type, class index_type>
  void accumulate_scaling_and_write_alpha_to_file(
      std::vector<index_type> const& sequence,
      maikel::hmm::hidden_markov_model<float_type> const& model)
  {
    std::size_t states = model.states();
//    std::vector<Eigen::RowVectorXd> alphas(T, Eigen::RowVectorXd(states));
    std::ofstream alphas("alphas.bin", std::ofstream::binary);
    BOOST_LOG_TRIVIAL(info) << "Starting forward algorithm with storing scaling factors into std::vector.";
    BOOST_LOG_TRIVIAL(info) << "Use accumulate on a view::transformed scaling list.";
    float_type logprob = 0.0;
    std::size_t datalen = sizeof(float_type)*states;
    { MAIKEL_PROFILER;
      std::ostreambuf_iterator<char> out(alphas);
      for (auto&& scaled_alpha : maikel::hmm::forward(sequence, model)) {
        logprob += std::log(scaled_alpha.first);
        std::copy_n(reinterpret_cast<const char*>(scaled_alpha.second.data()), datalen, out);
      }
    }
    std::cout << -logprob << std::endl;
  }

template <class T>
void read_alphas_from_bin(const maikel::hmm::hidden_markov_model<T>& hmm)
{
  MAIKEL_PROFILER;
  std::ifstream alphas("alphas.bin", std::ifstream::binary);
  Eigen::Matrix<T, 1, Eigen::Dynamic> alpha(hmm.states());
  std::size_t data_len = sizeof(T)*alpha.size();
  std::istreambuf_iterator<char> in(alphas), end;
  while (in != end) {
    std::copy_n(in, data_len, reinterpret_cast<char*>(alpha.data()));
    std::advance(in, data_len+1);
  }
}

int main(int argc, char *argv[])
{
  using namespace std;
  using namespace maikel::hmm;

  if (argc < 3) {
    cerr << "Usage: " << argv[0] << " <model.dat> <sequence.dat>\n";
    return exit_not_enough_arguments;
  }
  using float_type = double;
  using index_type = uint8_t;

  // read model
  ifstream model_input(argv[1]);
  auto model = read_hidden_markov_model<float_type>(model_input);

  vector<int> symbols { 0,1 };
  map<int,index_type> symbol_to_index = maikel::map_from_symbols<index_type>(symbols);
  ifstream sequence_input(argv[2]);
  vector<index_type> sequence = read_sequence(sequence_input, symbol_to_index);

  {
    MAIKEL_NAMED_PROFILER("v2::forward");
    float_type scaling = 0;
    for (auto&& alpha : forward(begin(sequence), end(sequence), model)) {
      scaling += log(alpha.first);
    }
    cout << -scaling << endl;
  }
  maikel::function_profiler::print_statistics(cout);

  return exit_success;
}


// Copyright (C) 2015 The Regents of the University of California (Regents).
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//
//     * Neither the name of The Regents or University of California nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Please contact the author of this library if you have any questions.
// Author: Chris Sweeney (cmsweeney@cs.ucsb.edu)

#include "theia/sfm/pose/seven_point_fundamental_matrix.h"

#include <Eigen/Core>
#include <Eigen/LU>
#include <glog/logging.h>
#include <vector>

#include "theia/math/polynomial.h"
#include "theia/sfm/pose/util.h"

namespace theia {

using Eigen::Matrix;

namespace {

// Sets up the constraint y^t * F * x = 0 such that M * F_v = 0 where M is a 7x9
// matrix and F_v is the vector containing the entries of F.
Matrix<double, 7, 9> SetupEpipolarConstraint(
    const std::vector<Eigen::Vector2d>& image1_points,
    const std::vector<Eigen::Vector2d>& image2_points) {
  Matrix<double, 7, 9> epipolar_constraint;
  for (int i = 0; i < 7; i++) {
    // Fill matrix with the epipolar constraint from q'_t*E*q = 0. Where q is
    // from the first image, and q' is from the second.
    epipolar_constraint.row(i) <<
        image2_points[i].x() * image1_points[i].x(),
        image2_points[i].y() * image1_points[i].x(),
        image1_points[i].x(),
        image2_points[i].x() * image1_points[i].y(),
        image2_points[i].y() * image1_points[i].y(),
        image1_points[i].y(),
        image2_points[i].x(),
        image2_points[i].y(),
        1.0;
  }

  return epipolar_constraint;
}

}  // namespace

bool SevenPointFundamentalMatrix(
    const std::vector<Eigen::Vector2d>& image1_points,
    const std::vector<Eigen::Vector2d>& image2_points,
    std::vector<Eigen::Matrix3d>* fundamental_matrices) {
  CHECK_EQ(image1_points.size(), 7);
  CHECK_EQ(image2_points.size(), 7);
  CHECK_NOTNULL(fundamental_matrices)->clear();

  std::vector<Eigen::Vector2d> norm_img1_points(image1_points.size());
  std::vector<Eigen::Vector2d> norm_img2_points(image2_points.size());

  // Normalize the image points.
  Eigen::Matrix3d img1_norm_mat, img2_norm_mat;
  NormalizeImagePoints(image1_points, &norm_img1_points, &img1_norm_mat);
  NormalizeImagePoints(image2_points, &norm_img2_points, &img2_norm_mat);

  const Matrix<double, 7, 9>& epipolar_constraint =
      SetupEpipolarConstraint(norm_img1_points, norm_img2_points);

  const Eigen::FullPivLU<Matrix<double, 7, 9> > lu(epipolar_constraint);
  if (lu.dimensionOfKernel() != 2) {
    return false;
  }

  // Represent F in terms of its null space such that F = x * F1' + (1 - x) * F2
  // where F1 and F2 are vectors in the null space of F. Note that this can also
  // be parameterized such that:
  //   F = x * F1' + (1 - x) * F2 = x * (F1' - F2) + F2 = x * F1 + F2.
  const Matrix<double, 9, 2>& null_space = lu.kernel();
  const Matrix<double, 9, 1> F1_vec = null_space.col(0) - null_space.col(1);
  const Eigen::Map<const Eigen::Matrix3d> F1(F1_vec.data());
  const Eigen::Map<const Eigen::Matrix3d> F2(null_space.col(1).data());

  // This is the cubic equation resulting from det(x * F1 + F2) = 0.
  Eigen::VectorXd determinant_constraint(4);
  determinant_constraint(0) =
      -(F2(1, 2) * F2(2, 1) - F2(1, 1) * F2(2, 2)) * F2(0, 0) +
      (F2(0, 2) * F2(2, 1) - F2(0, 1) * F2(2, 2)) * F2(1, 0) -
      (F2(0, 2) * F2(1, 1) - F2(0, 1) * F2(1, 2)) * F2(2, 0);
  determinant_constraint(1) =
      -(F2(1, 2) * F2(2, 1) - F2(1, 1) * F2(2, 2)) * F1(0, 0) +
      (F2(0, 2) * F2(2, 1) - F2(0, 1) * F2(2, 2)) * F1(1, 0) -
      (F2(0, 2) * F2(1, 1) - F2(0, 1) * F2(1, 2)) * F1(2, 0) +
      (F1(2, 2) * F2(1, 1) - F1(2, 1) * F2(1, 2) - F1(1, 2) * F2(2, 1) +
       F1(1, 1) * F2(2, 2)) *
          F2(0, 0) -
      (F1(2, 2) * F2(0, 1) - F1(2, 1) * F2(0, 2) - F1(0, 2) * F2(2, 1) +
       F1(0, 1) * F2(2, 2)) *
          F2(1, 0) +
      (F1(1, 2) * F2(0, 1) - F1(1, 1) * F2(0, 2) - F1(0, 2) * F2(1, 1) +
       F1(0, 1) * F2(1, 2)) *
          F2(2, 0);
  determinant_constraint(2) =
      (F1(2, 2) * F2(1, 1) - F1(2, 1) * F2(1, 2) - F1(1, 2) * F2(2, 1) +
       F1(1, 1) * F2(2, 2)) *
          F1(0, 0) -
      (F1(2, 2) * F2(0, 1) - F1(2, 1) * F2(0, 2) - F1(0, 2) * F2(2, 1) +
       F1(0, 1) * F2(2, 2)) *
          F1(1, 0) +
      (F1(1, 2) * F2(0, 1) - F1(1, 1) * F2(0, 2) - F1(0, 2) * F2(1, 1) +
       F1(0, 1) * F2(1, 2)) *
          F1(2, 0) -
      (F1(1, 2) * F1(2, 1) - F1(1, 1) * F1(2, 2)) * F2(0, 0) +
      (F1(0, 2) * F1(2, 1) - F1(0, 1) * F1(2, 2)) * F2(1, 0) -
      (F1(0, 2) * F1(1, 1) - F1(0, 1) * F1(1, 2)) * F2(2, 0);
  determinant_constraint(3) =
      -(F1(1, 2) * F1(2, 1) - F1(1, 1) * F1(2, 2)) * F1(0, 0) +
      (F1(0, 2) * F1(2, 1) - F1(0, 1) * F1(2, 2)) * F1(1, 0) -
      (F1(0, 2) * F1(1, 1) - F1(0, 1) * F1(1, 2)) * F1(2, 0);

  // Solve the cubic equation for x.
  Eigen::VectorXd roots;
  FindPolynomialRoots(determinant_constraint, &roots, NULL);

  for (int i = 0; i < roots.size(); i++) {
    // Compose the fundamental matrix solution from the null space and
    // determinant constraint: F = x * F1 + F2;
    fundamental_matrices->emplace_back(img2_norm_mat.transpose() *
                                       (roots(i) * F1 + F2) * img1_norm_mat);
  }
  return fundamental_matrices->size() > 0;
}

}  // namespace theia


/// \file   interval.hpp
///
/// \brief
///
/// \authors    Maarten P. Scholl
/// \date       2018-01-31
/// \copyright  Copyright 2017-2019 The Institute for New Economic Thinking,
///             Oxford Martin School, University of Oxford
///
///             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.
///
///             You may obtain instructions to fulfill the attribution
///             requirements in CITATION.cff
///
#ifndef ESL_MATHEMATICS_INTERVAL_HPP
#define ESL_MATHEMATICS_INTERVAL_HPP

#include <sstream>
#include <type_traits>

#include <boost/serialization/serialization.hpp>

namespace esl::mathematics {
    ///
    /// \brief  A set of numbers lying between a lower and upper endpoint. The
    ///         endpoints may be included in the set or not, if the lower is
    ///         included the interval is left_closed_, and if the upper is
    ///         included  the interval is right_closed_.
    ///
    /// \tparam number_t_
    /// \tparam left_closed_
    /// \tparam right_closed_
    template<typename number_t_,
             bool left_closed_  = true,
             bool right_closed_ = true>
    struct interval
    {
        ///
        /// \brief Specifies whether the interval includes the lower value
        ///
        /// \return
        constexpr static bool left_closed()
        {
            return left_closed_;
        }

        ///
        /// \brief Specifies whether the interval includes the upper value
        ///
        /// \return
        constexpr static bool right_closed()
        {
            return right_closed_;
        }

        static_assert(std::is_floating_point<number_t_>::value
                      // TODO: || esl::is_rational<number_t_>::value
                      || std::is_integral<number_t_>::value);

        number_t_ lower;
        number_t_ upper;

        ///
        /// \brief  default interval constructor sets the lower and upper bound
        ///         to time_point(0)
        ///
        constexpr interval()
        : lower(0)
        , upper(0)
        {

        }

        ///
        /// \brief  constructs an interval from `lower` to `upper`
        ///
        /// \param lower    lower bound
        /// \param upper    upper bound
        constexpr interval(number_t_ lower, number_t_ upper)
        : lower(lower)
        , upper(upper)
        {

        }

        ///
        /// \return true iff the interval contains no elements
        ///
        [[nodiscard]] constexpr bool empty() const
        {
            if(lower > upper) {
                return true;
            }

            if(lower == upper) {
                return left_closed_ || right_closed_;
            }

            // (lower < upper) is implied
            if(1 == upper - lower){
               return left_closed_ && right_closed_;
            }

            return false;
        }

        ///
        /// \return true iff interval contains exactly one element
        ///
        [[nodiscard]] constexpr bool singleton() const
        {
            bool sufficient_ = !left_closed_ && !right_closed_ && lower == upper;
            if(std::is_floating_point<number_t_>::value || sufficient_) {
                // || TODO: esl::is_rational<number_t_>::value
                return sufficient_;
            }

            // is_integral is implied from here
            bool asymmetric_ =
                (1 == upper - lower) && (left_closed_ != right_closed_);
            bool symmetric_ =
                (2 == upper - lower) && (left_closed_ && right_closed_);
            return (upper > lower) && (asymmetric_ || symmetric_);
        }

        ///
        /// \return true iff the interval is singleton or empty
        ///
        [[nodiscard]] constexpr bool degenerate() const
        {
            return empty() || singleton();
        }

        ///
        /// \param value element to test
        /// \return true iff element is in contained in interval
        ///
        [[nodiscard]] constexpr bool contains(number_t_ value) const
        {
            return (lower < value || (left_closed_ && lower == value))
                   && (upper > value || (right_closed_ && upper == value));
        }

        ///
        /// \brief  renders the interval to a string as detailed in the class's
        ///         ostream operator implementation
        ///
        /// \return
        [[nodiscard]] std::string representation() const
        {
            std::stringstream stream_;
            stream_ << *this;
            return stream_.str();
        }

        ///
        /// \brief  renders the interval using '[' and ']' to denote open lower
        ///         and upper bounds respectively, and '(' and ')' for closed
        ///         lower and upper bounds.
        ///
        /// \param stream
        /// \param self
        /// \return
        friend std::ostream &
        operator<<(std::ostream &stream,
                   const interval<number_t_, left_closed_, right_closed_> &self)
        {
            stream << (left_closed_ ? '[' : '(');
            stream << self.lower << ',' << self.upper;
            stream << (right_closed_ ? ']' : ')');
            return stream;
        }

        ///
        /// \tparam archive_t
        /// \param archive
        /// \param version
        template<class archive_t>
        void serialize(archive_t &archive, const unsigned int version)
        {
            (void)version;
            archive &BOOST_SERIALIZATION_NVP(lower);
            archive &BOOST_SERIALIZATION_NVP(upper);
        }
    };
}  // namespace esl

#endif  // ESL_MATHEMATICS_INTERVAL_HPP


/* Copyright 2018 Ignacio Torroba (ignaciotb@kth.se)
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef UTILS_MATRICES_HPP
#define UTILS_MATRICES_HPP

#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/matrix_expression.hpp>
#include <boost/numeric/ublas/operation_blocked.hpp>
#include <boost/numeric/ublas/operation.hpp>
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/vector_expression.hpp>
#include <boost/numeric/ublas/io.hpp>
#include <boost/numeric/ublas/triangular.hpp>
#include <boost/numeric/ublas/lu.hpp>

#include <boost/scoped_ptr.hpp>

#include <boost/math/distributions/chi_squared.hpp>
#include <boost/math/distributions/inverse_chi_squared.hpp>

namespace matrices{

    template<typename T>
    T matDeterminant(const boost::numeric::ublas::matrix<T>& mat_A){
        using namespace boost::numeric::ublas;
        matrix<T> mLu(mat_A);
        permutation_matrix<std::size_t> pivots(mat_A.size1());

        auto isSingular = lu_factorize(mLu, pivots);
        if (isSingular){
            return static_cast<T>(0);
        }

        T det = static_cast<T>(1);
        for (std::size_t i = 0; i < pivots.size(); ++i){
            if (pivots(i) != i){
                det *= static_cast<T>(-1);
            }
            det *= mLu(i, i);
        }
        return det;
    }

    template<typename T>
    bool InvertMatrix (const boost::numeric::ublas::matrix<T>& input, boost::numeric::ublas::matrix<T>& inverse) {
        using namespace boost::numeric::ublas;
        matrix<T> A(input);
        // Perform LU-factorization
        permutation_matrix<std::size_t> pm(A.size1());
        int res = lu_factorize(A,pm);
        if( res != 0 )
            return false;
        inverse.assign(identity_matrix<T>(A.size1()));
        lu_substitute(A, pm, inverse);
        return true;
    }

    template<typename T>
    boost::numeric::ublas::matrix<T> Cholesky(const boost::numeric::ublas::matrix<T>& mat_A){
        // TODO_NACHO: check for matrix conditions to use cholesky
        int n = mat_A.size1();
        boost::numeric::ublas::matrix<T> chol_triang(n, n);
        for(unsigned int i=0; i< mat_A.size1(); i++){
            for(unsigned int j=0; j< i + 1; j++){
                double s = 0;
                for(unsigned int k = 0; k<j; k++){
                    s += chol_triang(i * n + k) * chol_triang(j * n + k);
                }
                chol_triang(i * n + j) = (i = j)?
                            std::sqrt(mat_A(i * n + i) - s):
                            (1.0 / chol_triang(j * n + j) * (mat_A(i * n + j) - s));
            }
        }
        return chol_triang;
    }

    template<typename T>
    boost::numeric::ublas::matrix<T> matTriangDeterminant(const boost::numeric::ublas::matrix<T>& mat_A){
        int n = mat_A.size1();
        T det;
        for(unsigned int i=0; i< mat_A.size1(); i++){
            for(unsigned int j=0; j< mat_A.size2(); j++){
                det *= (i == j)? mat_A(i,j): 1;
            }
        }
        return det;
    }
}

#endif // UTILS_MATRICES_HPP


/*
 * resampling.hpp
 *
 *  Created on: Mar 28, 2019
 *      Author: Gregory Kramida
 *   Copyright: 2019 Gregory Kramida
 *
 *   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.
 */

#pragma once

//libraries
#include <Eigen/Dense>
#include <unsupported/Eigen/CXX11/Tensor>

namespace math {

/**
 * Different strategies for upsampling a discrete field
 */
enum class UpsamplingStrategy {
	NEAREST = 0, ///@see upsampleX2_nearest for details
	LINEAR = 1 ///@see upsampleX2_linear for details
};

/**
 * Different strategies for downsampling a discrete field
 */
enum class DownsamplingStrategy {
	AVERAGE = 0, ///@see downsampleX2_average for details
	LINEAR = 1 ///@see downsampleX2_linear for details
};

/**
 * Upsample the field such that the output is a field 2X larger than the original in each dimension.
 * @param field input field
 * @param upsampling_strategy -- which upsampling strategy to use.
 * @return upsampled field
 */
template<typename Scalar>
Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor> upsampleX2(
		const Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>& field,
		UpsamplingStrategy upsampling_strategy = UpsamplingStrategy::NEAREST);
/**
 * Upsample the field such that the output is a field 2X larger than the original in each dimension.
 * @overload
 */
template<typename Scalar>
Eigen::Tensor<Scalar, 3, Eigen::ColMajor> upsampleX2(
		const Eigen::Tensor<Scalar, 3, Eigen::ColMajor>& field,
		UpsamplingStrategy upsampling_strategy = UpsamplingStrategy::NEAREST);

/**
 * Upsample the field such that the output is a field 2X larger than the original in each dimension.
 * This procedure uses a simple box filter / no interpolation, i.e. simply copies the value to it's immediate "children"
 * in the upsampled version.
 * Conceptual example:
 * ⎡1  2⎤
 * ⎣3  4⎦
 * yields
 * ⎡1  1  2  2⎤
 * ⎢1  1  2  2⎥
 * ⎢3  3  4  4⎥
 * ⎣3  3  4  4⎦
 * @param field input field
 * @return upsampled field
 */
template<typename Scalar>
Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor> upsampleX2_nearest(
		const Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>& field);

/**
 * Upsample the field such that the output is a field 2X larger than the original in each dimension using the
 * nearest-neighbor (NEAREST) strategy.
 * @overload
 */
template<typename Scalar>
Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> upsampleX2_nearest(
		const Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>& field);

/**
 * Upsample the field such that the output is a field 2X larger than the original in each dimension.
 * @overload
 */
template<typename Scalar>
Eigen::Tensor<Scalar, 3, Eigen::ColMajor> upsampleX2_nearest(
		const Eigen::Tensor<Scalar, 3, Eigen::ColMajor>& field);

/**
 * Upsample the field such that the output is a field 2X larger than the original in each dimension using bilinear
 * filtering. This procedure uses a simple tent filter in each dimension to compute the values, i.e. bilinear filtering.
 * Conceptual example:
 * The influence coefficients for the voxels in the output field (o) fall off linearly from 1.0 at the
 * current input voxel (X) to 0.0 at it's neighbors (O).
 *    o     o    o     o    o     o
 *       O┈┈┈┈┈┈┈┈┈┈O┈┈┈┈┈┈┈┈┈┈O
 *    o  ┊  o    o     o    o  ┊  o
 *       ┊                     ┊
 *    o  ┊  o    o     o    o  ┊  o
 *       O          X          O
 *    o  ┊  o    o     o    o  ┊  o
 *       ┊                     ┊
 *    o  ┊  o    o     o    o  ┊  o
 *       O┈┈┈┈┈┈┈┈┈┈O┈┈┈┈┈┈┈┈┈┈O
 *    o     o    o     o    o     o
 *  Boundary voxels are processed as if the boundary values of the input repeat infinitely.
 *
 * @param field input field
 * @return upsampled field
 */
template<typename Scalar>
Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor> upsampleX2_linear(
		const Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>& field);
/**
 * Upsample the field such that the output is a field 2X larger than the original in each dimension using bilinear
 * interpolation (LINEAR) strategy.
 * @overload
 */
template<typename Scalar>
Eigen::Tensor<Scalar, 3, Eigen::ColMajor> upsampleX2_linear(
		const Eigen::Tensor<Scalar, 3, Eigen::ColMajor>& field);

/**
 * Downsample the provided matrix using a box filter such that each dimension of the downsampled field is half the
 * corresponding dimension of the input field.
 * @param field input field
 * @param downsampling_strategy strategy to use for downsampling
 * @return downsampled field
 */
template<typename Scalar>
Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor> downsampleX2(
		const Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>& field,
		DownsamplingStrategy downsampling_strategy = DownsamplingStrategy::AVERAGE);
/**
 * Downsample the provided matrix using a box filter such that each dimension of the downsampled field is half the
 * corresponding dimension of the input field.
 * @overload
 */
template<typename Scalar>
Eigen::Tensor<Scalar, 3, Eigen::ColMajor> downsampleX2(
		const Eigen::Tensor<Scalar, 3, Eigen::ColMajor>& field,
		DownsamplingStrategy downsampling_strategy = DownsamplingStrategy::AVERAGE);

/**
 * Downsample the provided matrix using a box filter such that each dimension of the downsampled field is half the
 * corresponding dimension of the input field. Uses a simple box filter, i.e. each "downsampled" value will be the
 * average of it's source values in the input.
 *
 * Conceptual example (for 2d case):
 * ⎡1  2  4  5⎤
 * ⎢2  3  5  6⎥
 * ⎢1  3  6  7⎥
 * ⎣3  5  7  8⎦
 * yields
 * ⎡2  5⎤
 * ⎣3  7⎦
 *
 * @param field input field
 * @return downsampled field
 */
template<typename Scalar>
Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor> downsampleX2_average(
		const Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>& field);
/**
 * Downsample the provided matrix using a box filter such that each dimension of the downsampled field is half the
 * corresponding dimension of the input field using simple averaging (AVERAGE strategy).
 * @overload
 */
template<typename Scalar>
Eigen::Tensor<Scalar, 3, Eigen::ColMajor> downsampleX2_average(
		const Eigen::Tensor<Scalar, 3, Eigen::ColMajor>& field);

/**
 * Downsample the provided matrix using a box filter such that each dimension of the downsampled field is half the
 * corresponding dimension of the input field. Uses a tent filter, i.e. each "downsampled" value will be influenced by
 * values of the input weighted by the inverse ratio of their distance to the neighbor values.
 *
 * Conceptual example:
 * The influence coefficients for the source voxels in the input field (x) fall off linearly from 1.0 at the current
 * target voxel (X) to 0.0 at it's neighbors (O).
 *    o     o    o     o    o     o
 *       O┈┈┈┈┈┈┈┈┈┈O┈┈┈┈┈┈┈┈┈┈O
 *    o  ┊  o    o     o    o  ┊  o
 *       ┊                     ┊
 *    o  ┊  o    o     o    o  ┊  o
 *       O          X          O
 *    o  ┊  o    o     o    o  ┊  o
 *       ┊                     ┊
 *    o  ┊  o    o     o    o  ┊  o
 *       O┈┈┈┈┈┈┈┈┈┈O┈┈┈┈┈┈┈┈┈┈O
 *    o     o    o     o    o     o
 *  Boundary voxels are processed as if the boundary values of the input repeat infinitely.
 *
 * @param field input field
 * @return downsampled field
 */
template<typename Scalar>
Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor> downsampleX2_linear(
		const Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>& field);
/**
 * Downsample the provided matrix using a box filter such that each dimension of the downsampled field is half the
 * corresponding dimension of the input field using bilinear interpolation (LINEAR strategy).
 * @overload
 */
template<typename Scalar>
Eigen::Tensor<Scalar, 3, Eigen::ColMajor> downsampleX2_linear(
		const Eigen::Tensor<Scalar, 3, Eigen::ColMajor>& field);

} // namespace math


#include <chrono>
#include <iostream>
#include <limits>
#include <Eigen/Dense>
#include "dopri.h"
#include "kepler.h"
#include "elements.h"

using Eigen::VectorXd;
using Eigen::Vector3d;
using std::pow;
using std::sqrt;

namespace dopri {
    void gravity(int *n, double *x, double *y, double *f, double *rpar, int *ipar) {
        auto r = sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);
        auto r3 = r*r*r;
        f[0] = y[3];
        f[1] = y[4];
        f[2] = y[5];
        f[3] = -rpar[0] * y[0] / r3;
        f[4] = -rpar[0] * y[1] / r3;
        f[5] = -rpar[0] * y[2] / r3;
    }

    void solout_dummy(int *nr, double *xold, double *x, double *y, int *n, double *con,
                      int *icomp, int *nd, double *rpar, int *ipar, int *irtrn, double *xout){};

    void integrate(void (*func)(int *, double *, double *, double *, double *, int *),
            double *x, VectorXd *rv, double xend, double rpar[], int ipar[],
            double reltol = 1e-6, double abstol = 1e-8) {
        int n = rv->size();
        double rtol[] = {reltol};
        double atol[] = {abstol};
        int itol = 0;
        int iout = 0;
        int lwork = 11*n+8*n+21;
        int liwork = n + 21;
        double work[lwork];
        memset(work, 0, sizeof(work));
        int iwork[liwork];
        memset(iwork, 0, sizeof(iwork));
        int idid = 0;
        c_dop853(&n, func, x, rv->data(), &xend, rtol, atol, &itol, &solout_dummy,
            &iout, work, &lwork, iwork, &liwork, rpar, ipar, &idid);
    }

    void benchmark(int times) {
        auto mu = 3.986004418e5;
        Vector3d r(8.59072560e+02, -4.13720368e+03, 5.29556871e+03);
        Vector3d v(7.37289205e+00, 2.08223573e+00, 4.39999794e-01);
        VectorXd rv(r.size()+v.size());
        rv << r, v;
        VectorXd rv0(rv);
        auto el = elements::elements(r, v, mu);
        auto x = 0.0;
        double rpar[] = {mu};
        int ipar[] = {0};
        auto xend = kepler::period(el[0], mu);
        auto best = std::numeric_limits<double>::infinity();
        auto worst = -std::numeric_limits<double>::infinity();
        double all = 0;
        for (auto i=0; i < times; i++) {
            auto begin = std::chrono::high_resolution_clock::now();
            integrate(&gravity, &x, &rv0, xend, rpar, ipar);
            auto end = std::chrono::high_resolution_clock::now();
            auto current = std::chrono::duration_cast<std::chrono::nanoseconds>(end-begin).count()/1e9;
            all += current;
            if (current < best) {
                best = current;
            }
            if (current > worst) {
                worst = current;
            }
            rv0 = rv;
            x = 0;
        }
        std::cout << "[" << all/times << "," << best << "," << worst << "]" << std::endl;
    }
}


#include <iostream>
#include <string>
#include <cstdlib>
#include <boost/mpl/string.hpp>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/size_t.hpp>

using namespace std;
using namespace boost;

///////////////////////////////////////////////////////////////////////////////
// exponentiation calculations
template <int accum, int base, int exp> struct POWER_CORE : POWER_CORE<accum * base, base, exp - 1>{};

template <int accum, int base>
struct POWER_CORE<accum, base, 0>
{
    enum : int { val = accum };
};

template <int base, int exp> struct POWER : POWER_CORE<1, base, exp>{};

///////////////////////////////////////////////////////////////////////////////
// # of digit calculations
template <int depth, unsigned int i> struct NUM_DIGITS_CORE : NUM_DIGITS_CORE<depth + 1, i / 10>{};

template <int depth>
struct NUM_DIGITS_CORE<depth, 0>
{
    enum : int { val = depth};
};

template <int i> struct NUM_DIGITS : NUM_DIGITS_CORE<0, i>{};

template <>
struct NUM_DIGITS<0>
{
    enum : int { val = 1 };
};

///////////////////////////////////////////////////////////////////////////////
// Convert digit to character (1 -> '1')
template <int i>
struct DIGIT_TO_CHAR
{
    enum : char{ val = i + 48 };
};

///////////////////////////////////////////////////////////////////////////////
// Find the digit at a given offset into a number of the form 0000000017
template <unsigned int i, int place> // place -> [0 .. 10]
struct DIGIT_AT
{
    enum : char{ val = (i / POWER<10, place>::val) % 10 };
};

struct NULL_CHAR
{
    enum : char{ val = '\0' };
};

///////////////////////////////////////////////////////////////////////////////
// Convert the digit at a given offset into a number of the form '0000000017' to a character
template <unsigned int i, int place> // place -> [0 .. 9]
    struct ALT_CHAR : DIGIT_TO_CHAR< DIGIT_AT<i, place>::val >{};

///////////////////////////////////////////////////////////////////////////////
// Convert the digit at a given offset into a number of the form '17' to a character

// Template description, with specialization to generate null characters for out of range offsets
template <unsigned int i, int offset, int numDigits, bool inRange>
    struct OFFSET_CHAR_CORE_CHECKED{};
template <unsigned int i, int offset, int numDigits>
    struct OFFSET_CHAR_CORE_CHECKED<i, offset, numDigits, false> : NULL_CHAR{};
template <unsigned int i, int offset, int numDigits>
    struct OFFSET_CHAR_CORE_CHECKED<i, offset, numDigits, true>  : ALT_CHAR<i, (numDigits - offset) - 1 >{};

// Perform the range check and pass it on
template <unsigned int i, int offset, int numDigits>
    struct OFFSET_CHAR_CORE : OFFSET_CHAR_CORE_CHECKED<i, offset, numDigits, offset < numDigits>{};

// Calc the number of digits and pass it on
template <unsigned int i, int offset>
    struct OFFSET_CHAR : OFFSET_CHAR_CORE<i, offset, NUM_DIGITS<i>::val>{};

///////////////////////////////////////////////////////////////////////////////
// Integer to char* template. Works on unsigned ints.
template <unsigned int i>
struct IntToStr
{
    const static char str[];
    typedef typename mpl::string<
    OFFSET_CHAR<i, 0>::val,
    OFFSET_CHAR<i, 1>::val,
    OFFSET_CHAR<i, 2>::val,
    OFFSET_CHAR<i, 3>::val,
    OFFSET_CHAR<i, 4>::val,
    OFFSET_CHAR<i, 5>::val,
    /*OFFSET_CHAR<i, 6>::val,
    OFFSET_CHAR<i, 7>::val,
    OFFSET_CHAR<i, 8>::val,
    OFFSET_CHAR<i, 9>::val,*/
    NULL_CHAR::val>::type type;
};

template <unsigned int i>
const char IntToStr<i>::str[] =
{
    OFFSET_CHAR<i, 0>::val,
    OFFSET_CHAR<i, 1>::val,
    OFFSET_CHAR<i, 2>::val,
    OFFSET_CHAR<i, 3>::val,
    OFFSET_CHAR<i, 4>::val,
    OFFSET_CHAR<i, 5>::val,
    OFFSET_CHAR<i, 6>::val,
    OFFSET_CHAR<i, 7>::val,
    OFFSET_CHAR<i, 8>::val,
    OFFSET_CHAR<i, 9>::val,
    NULL_CHAR::val
};

template <bool condition, class Then, class Else>
struct IF
{
    typedef Then RET;
};

template <class Then, class Else>
struct IF<false, Then, Else>
{
    typedef Else RET;
};

template < typename Str1, typename Str2 >
struct concat : mpl::insert_range<Str1, typename mpl::end<Str1>::type, Str2> {};
template <typename Str1, typename Str2, typename Str3 >
struct concat3 : mpl::insert_range<Str1, typename mpl::end<Str1>::type, typename concat<Str2, Str3 >::type > {};

typedef typename mpl::string<'f','i','z','z'>::type fizz;
typedef typename mpl::string<'b','u','z','z'>::type buzz;
typedef typename mpl::string<'\r', '\n'>::type mpendl;
typedef typename concat<fizz, buzz>::type fizzbuzz;

// discovered boost mpl limitation on some length

template <int N>
struct FizzBuzz
{
    typedef typename concat3<typename FizzBuzz<N - 1>::type, typename IF<N % 15 == 0, typename fizzbuzz::type, typename IF<N % 3 == 0, typename fizz::type, typename IF<N % 5 == 0, typename buzz::type, typename IntToStr<N>::type >::RET >::RET >::RET, typename mpendl::type>::type type;
};

template <>
struct FizzBuzz<1>
{
    typedef mpl::string<'1','\r','\n'>::type type;
};

int main(int argc, char** argv)
{
    const int n = 7;
    std::cout << mpl::c_str<FizzBuzz<n>::type>::value << std::endl;
	return 0;
}


/**
 * @file    MatrixPseudoInverse.cpp
 * @brief   Functions for matrix pseudo inverse, and matrix square root.
 * @author  Jianzhu Huai
 */

#ifndef INCLUDE_OKVIS_MATRIX_PSEUDO_INVERSE_HPP
#define INCLUDE_OKVIS_MATRIX_PSEUDO_INVERSE_HPP

#include <Eigen/Core>
#include <Eigen/Eigenvalues>

#include <okvis/assert_macros.hpp>

namespace okvis {

/**
 * \brief Compute the square root of a matrix using the LDLt decomposition for
 * square, positive semidefinite matrices
 *
 * To reconstruct the input matrix, \f$ \mathbf A \f$, from the returned matrix,
 * \f$ \mathbf S \f$, use, \f$ \mathbf A = \mathbf S \mathbf S^T \f$.
 *
 *
 * @param inMatrix      The square matrix whose square root should be computed.
 * @param outMatrixSqrt The output square root.
 */
template <typename DERIVED1, typename DERIVED2>
/*Eigen::ComputationInfo*/ void
computeMatrixSqrt(const Eigen::MatrixBase<DERIVED1> &inMatrix,
                  const Eigen::MatrixBase<DERIVED2> &outMatrixSqrt) {
  OKVIS_ASSERT_EQ_DBG(std::runtime_error, inMatrix.rows(), inMatrix.cols(),
                      "This method is only valid for square input matrices");

  DERIVED2 &result = const_cast<DERIVED2 &>(outMatrixSqrt.derived());

  // This is tricky. Using the output matrix type causes the input matrix
  // type to be upgraded to a real numeric matrix. This is useful if,
  // for example, the inMatrix is something like Eigen::Matrix3d::Identity(),
  // which is not an actual matrix. Using DERIVED1 as the template argument
  // in that case will cause a firestorm of compiler errors.
  Eigen::LDLT<DERIVED2> ldlt(inMatrix.derived());
  result = ldlt.matrixL();
  result = ldlt.transpositionsP().transpose() * result;
  result *= ldlt.vectorD().array().sqrt().matrix().asDiagonal();

  // return ldlt.info();
}

class MatrixPseudoInverse
{
public:
  OKVIS_DEFINE_EXCEPTION(Exception,std::runtime_error)
  /**
   * @brief Pseudo inversion of a symmetric matrix.
   * @warning   This uses Eigen-decomposition, it assumes the input is symmetric positive semi-definite
   *            (negative Eigenvalues are set to zero).
   * @tparam Derived Matrix type (auto-deducible).
   * @param[in] a Input Matrix
   * @param[out] result Output, i.e. pseudo-inverse.
   * @param[in] epsilon The tolerance.
   * @param[out] rank Optional rank.
   * @return
   */
  template<typename Derived>
  static bool pseudoInverseSymm(
      const Eigen::MatrixBase<Derived>&a,
      const Eigen::MatrixBase<Derived>&result, double epsilon =
          std::numeric_limits<typename Derived::Scalar>::epsilon(), int * rank = 0);

  /**
   * @brief Pseudo inversion and square root (Cholesky decomposition) of a symmetric matrix.
   * @warning   This uses Eigen-decomposition, it assumes the input is symmetric positive semi-definite
   *            (negative Eigenvalues are set to zero). Also if the input is positive semi-definite,
   *            its zero eigenvalues are at the lower part of the diagonal.
   * @tparam Derived Matrix type (auto-deducible).
   * @param[in] a Input Matrix, \f$A\f$.
   * @param[out] result Output, \f$L\f$, i.e. the Cholesky decomposition of a pseudo-inverse, \f$A^{-1} = L L^*\f$.
   * @param[in] epsilon The tolerance.
   * @param[out] rank The rank, if of interest.
   * @return
   */
  template<typename Derived>
  static bool pseudoInverseSymmSqrt(
      const Eigen::MatrixBase<Derived>&a,
      const Eigen::MatrixBase<Derived>&result, double epsilon =
          std::numeric_limits<typename Derived::Scalar>::epsilon(),
      int* rank = NULL);

  /**
   * @brief Pseudo square root (Cholesky decomposition) of a symmetric matrix.
   * @warning   This uses Eigen-decomposition, it assumes the input is symmetric positive semi-definite
   *            (negative Eigenvalues are set to zero). Also if the input is positive semi-definite,
   *            its zero eigenvalues are at the lower part of the diagonal.
   * @tparam Derived Matrix type (auto-deducible).
   * @param[in] a Input Matrix, \f$A\f$.
   * @param[out] result Output, \f$L\f$, i.e. the Cholesky decomposition of a pseudo-inverse, \f$A = L L^*\f$.
   * @param[in] epsilon The tolerance.
   * @param[out] rank The rank, if of interest.
   * @return
   */
  template<typename Derived>
  static bool pseudoSymmSqrt(
      const Eigen::MatrixBase<Derived>&a,
      const Eigen::MatrixBase<Derived>&result, double epsilon =
          std::numeric_limits<typename Derived::Scalar>::epsilon(),
      int* rank = NULL);

  /**
   * @brief Block-wise pseudo inversion of a symmetric matrix with non-zero diagonal blocks.
   * @warning   This uses Eigen-decomposition, it assumes the input is symmetric positive semi-definite
   *            (negative Eigenvalues are set to zero).
   * @tparam Derived Matrix type (auto-deducible).
   * @tparam blockDim The block size of the diagonal blocks.
   * @param[in] M_in Input Matrix
   * @param[out] M_out Output, i.e. thepseudo-inverse.
   * @param[in] epsilon The tolerance.
   * @return
   */
  template<typename Derived, int blockDim>
  static void blockPinverse(
      const Eigen::MatrixBase<Derived>& M_in,
      const Eigen::MatrixBase<Derived>& M_out, double epsilon =
          std::numeric_limits<typename Derived::Scalar>::epsilon());

  /**
   * @brief Block-wise pseudo inversion and square root (Cholesky decomposition)
   *        of a symmetric matrix with non-zero diagonal blocks.
   * @warning   This uses Eigen-decomposition, it assumes the input is symmetric positive semi-definite
   *            (negative Eigenvalues are set to zero).
   * @tparam Derived Matrix type (auto-deducible).
   * @tparam blockDim The block size of the diagonal blocks.
   * @param[in] M_in Input Matrix
   * @param[out] M_out Output, i.e. the Cholesky decomposition of a pseudo-inverse.
   * @param[in] epsilon The tolerance.
   * @return
   */
  template<typename Derived, int blockDim>
  static void blockPinverseSqrt(
      const Eigen::MatrixBase<Derived>& M_in,
      const Eigen::MatrixBase<Derived>& M_out, double epsilon =
          std::numeric_limits<typename Derived::Scalar>::epsilon());

};

// Pseudo inversion of a symmetric matrix.
// attention: this uses Eigen-decomposition, it assumes the input is symmetric positive semi-definite
// (negative Eigenvalues are set to zero)
template<typename Derived>
bool MatrixPseudoInverse::pseudoInverseSymm(
    const Eigen::MatrixBase<Derived>&a, const Eigen::MatrixBase<Derived>&result,
    double epsilon, int * rank) {

  OKVIS_ASSERT_TRUE_DBG(Exception, a.rows() == a.cols(),
                        "matrix supplied is not quadratic");

  Eigen::SelfAdjointEigenSolver<Derived> saes(a);

  typename Derived::Scalar tolerance = epsilon * a.cols()
      * saes.eigenvalues().array().maxCoeff();

  const_cast<Eigen::MatrixBase<Derived>&>(result) = (saes.eigenvectors())
      * Eigen::VectorXd(
          (saes.eigenvalues().array() > tolerance).select(
              saes.eigenvalues().array().inverse(), 0)).asDiagonal()
      * (saes.eigenvectors().transpose());

  if (rank) {
    *rank = 0;
    for (int i = 0; i < a.rows(); ++i) {
      if (saes.eigenvalues()[i] > tolerance)
        (*rank)++;
    }
  }

  return true;
}

// Pseudo inversion and square root (Cholesky decomposition) of a symmetric matrix.
// attention: this uses Eigen-decomposition, it assumes the input is symmetric positive semi-definite
// (negative Eigenvalues are set to zero)
template<typename Derived>
bool MatrixPseudoInverse::pseudoInverseSymmSqrt(
    const Eigen::MatrixBase<Derived>&a, const Eigen::MatrixBase<Derived>&result,
    double epsilon, int * rank) {

  OKVIS_ASSERT_TRUE_DBG(Exception, a.rows() == a.cols(),
                        "matrix supplied is not quadratic");

  Eigen::SelfAdjointEigenSolver<Derived> saes(a);

  typename Derived::Scalar tolerance = epsilon * a.cols()
      * saes.eigenvalues().array().maxCoeff();

  const_cast<Eigen::MatrixBase<Derived>&>(result) = (saes.eigenvectors())
      * Eigen::VectorXd(
          Eigen::VectorXd(
              (saes.eigenvalues().array() > tolerance).select(
                  saes.eigenvalues().array().inverse(), 0)).array().sqrt())
          .asDiagonal();

  if (rank) {
    *rank = 0;
    for (int i = 0; i < a.rows(); ++i) {
      if (saes.eigenvalues()[i] > tolerance)
        (*rank)++;
    }
  }

  return true;
}

template <typename Derived>
bool MatrixPseudoInverse::pseudoSymmSqrt(
    const Eigen::MatrixBase<Derived> &a,
    const Eigen::MatrixBase<Derived> &result, double epsilon, int *rank) {

  OKVIS_ASSERT_TRUE_DBG(Exception, a.rows() == a.cols(),
                        "matrix supplied is not quadratic");

  Eigen::SelfAdjointEigenSolver<Derived> saes(a);

  typename Derived::Scalar tolerance =
      epsilon * a.cols() * saes.eigenvalues().array().maxCoeff();

  const_cast<Eigen::MatrixBase<Derived> &>(result) =
      (saes.eigenvectors()) *
      Eigen::VectorXd(
          Eigen::VectorXd((saes.eigenvalues().array() > tolerance)
                              .select(saes.eigenvalues().array(), 0))
              .array()
              .sqrt())
          .asDiagonal();

  if (rank) {
    *rank = 0;
    for (int i = 0; i < a.rows(); ++i) {
      if (saes.eigenvalues()[i] > tolerance)
        (*rank)++;
    }
  }

  return true;
}

// Block-wise pseudo inversion of a symmetric matrix with non-zero diagonal blocks.
// attention: this uses Eigen-decomposition, it assumes the input is symmetric positive semi-definite
// (negative Eigenvalues are set to zero)
template<typename Derived, int blockDim>
void MatrixPseudoInverse::blockPinverse(
    const Eigen::MatrixBase<Derived>& M_in,
    const Eigen::MatrixBase<Derived>& M_out, double epsilon) {

  OKVIS_ASSERT_TRUE_DBG(Exception, M_in.rows() == M_in.cols(),
                        "matrix supplied is not quadratic");

  const_cast<Eigen::MatrixBase<Derived>&>(M_out).resize(M_in.rows(),
                                                        M_in.rows());
  const_cast<Eigen::MatrixBase<Derived>&>(M_out).setZero();
  for (int i = 0; i < M_in.cols(); i += blockDim) {
    Eigen::Matrix<double, blockDim, blockDim> inv;
    const Eigen::Matrix<double, blockDim, blockDim> in = M_in
        .template block<blockDim, blockDim>(i, i);
    //const Eigen::Matrix<double,blockDim,blockDim> in1=0.5*(in+in.transpose());
    pseudoInverseSymm(in, inv, epsilon);
    const_cast<Eigen::MatrixBase<Derived>&>(M_out)
        .template block<blockDim, blockDim>(i, i) = inv;
  }
}

// Block-wise pseudo inversion and square root (Cholesky decomposition)
// of a symmetric matrix with non-zero diagonal blocks.
// attention: this uses Eigen-decomposition, it assumes the input is symmetric positive semi-definite
// (negative Eigenvalues are set to zero)
template<typename Derived, int blockDim>
void MatrixPseudoInverse::blockPinverseSqrt(
    const Eigen::MatrixBase<Derived>& M_in,
    const Eigen::MatrixBase<Derived>& M_out, double epsilon) {

  OKVIS_ASSERT_TRUE_DBG(Exception, M_in.rows() == M_in.cols(),
                        "matrix supplied is not quadratic");

  const_cast<Eigen::MatrixBase<Derived>&>(M_out).resize(M_in.rows(),
                                                        M_in.rows());
  const_cast<Eigen::MatrixBase<Derived>&>(M_out).setZero();
  for (int i = 0; i < M_in.cols(); i += blockDim) {
    Eigen::Matrix<double, blockDim, blockDim> inv;
    const Eigen::Matrix<double, blockDim, blockDim> in = M_in
        .template block<blockDim, blockDim>(i, i);
    //const Eigen::Matrix<double,blockDim,blockDim> in1=0.5*(in+in.transpose());
    pseudoInverseSymmSqrt(in, inv, epsilon);
    const_cast<Eigen::MatrixBase<Derived>&>(M_out)
        .template block<blockDim, blockDim>(i, i) = inv;
  }
}

} // namespace okvis
#endif // INCLUDE_OKVIS_MATRIX_PSEUDO_INVERSE_HPP


#include <iostream>
//#include <boost/multiprecision/cpp_int.hpp>
// using namespace boost::multiprecision;
const int mx = 1e6 + 5;
const long int inf = 2e9;
typedef long long ll;
#define rep(i, n) for (i = 0; i < n; i++)
#define repp(i, a, b) for (i = a; i <= b; i++)
#define pii pair<int, int>
#define vpii vector<pii>
#define vi vector<int>
#define vll vector<ll>
#define r(x) scanf("%d", &x)
#define rs(s) scanf("%s", s)
#define gc getchar_unlocked
#define pc putchar_unlocked
#define mp make_pair
#define pb push_back
#define lb lower_bound
#define ub upper_bound
#define endl "\n"
#define fast                          \
    ios_base::sync_with_stdio(false); \
    cin.tie(NULL);                    \
    cout.tie(NULL);
using namespace std;
void in(int &x) {
    register int c = gc();
    x = 0;
    int neg = 0;
    for (; ((c < 48 || c > 57) && c != '-'); c = gc())
        ;
    if (c == '-') {
        neg = 1;
        c = gc();
    }
    for (; c > 47 && c < 58; c = gc()) {
        x = (x << 1) + (x << 3) + c - 48;
    }
    if (neg)
        x = -x;
}
void out(int n) {
    int N = n, rev, count = 0;
    rev = N;
    if (N == 0) {
        pc('0');
        return;
    }
    while ((rev % 10) == 0) {
        count++;
        rev /= 10;
    }
    rev = 0;
    while (N != 0) {
        rev = (rev << 3) + (rev << 1) + N % 10;
        N /= 10;
    }
    while (rev != 0) {
        pc(rev % 10 + '0');
        rev /= 10;
    }
    while (count--) pc('0');
}
ll parent[mx], arr[mx], node, edge;
vector<pair<ll, pair<ll, ll>>> v;
void initial() {
    int i;
    rep(i, node + edge) parent[i] = i;
}
int root(int i) {
    while (parent[i] != i) {
        parent[i] = parent[parent[i]];
        i = parent[i];
    }
    return i;
}
void join(int x, int y) {
    int root_x = root(x);  // Disjoint set union by rank
    int root_y = root(y);
    parent[root_x] = root_y;
}
ll kruskal() {
    ll mincost = 0, i, x, y;
    rep(i, edge) {
        x = v[i].second.first;
        y = v[i].second.second;
        if (root(x) != root(y)) {
            mincost += v[i].first;
            join(x, y);
        }
    }
    return mincost;
}
int main() {
    fast;
    while (1) {
        int i, j, from, to, cost, totalcost = 0;
        cin >> node >> edge;  // Enter the nodes and edges
        if (node == 0 && edge == 0)
            break;  // Enter 0 0 to break out
        initial();  // Initialise the parent array
        rep(i, edge) {
            cin >> from >> to >> cost;
            v.pb(mp(cost, mp(from, to)));
            totalcost += cost;
        }
        sort(v.begin(), v.end());
        // rep(i,v.size())
        // 	cout<<v[i].first<<"  ";
        cout << kruskal() << endl;
        v.clear();
    }
    return 0;
}


//
//  Copyright (c) 2018, Cem Bassoy, cem.bassoy@gmail.com
//  Copyright (c) 2019, Amit Singh, amitsingh19975@gmail.com
//
//  Distributed under the Boost Software License, Version 1.0. (See
//  accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//
//  The authors gratefully acknowledge the support of
//  Google and Fraunhofer IOSB, Ettlingen, Germany
//

#include <boost/numeric/ublas/tensor.hpp>
#include <boost/multiprecision/cpp_bin_float.hpp>

#include <ostream>

//NOLINTNEXTLINE
int main()
{
  namespace ublas = boost::numeric::ublas;

  try {
    using value   = float;
    using layout  = ublas::layout::first_order; // storage format
    using tensor  = ublas::tensor_dynamic<value,layout>;
//    constexpr auto ones  = ublas::ones<value,layout>{};
    constexpr auto zeros = ublas::zeros<value,layout>{};

    // creates a three-dimensional tensor with extents 3,4 and 2
    // tensor A stores single-precision floating-point number according
    // to the first-order storage format

    tensor A = zeros(3,4,2);

    // initializes the tensor with increasing values along the first-index
    // using a single index.
    auto vf = 1.0f;
    for(auto i = 0u; i < A.size(); ++i, vf += 1.0f)
      A[i] = vf;

    // formatted output
    std::cout << "% --------------------------- " << std::endl;
    std::cout << "% --------------------------- " << std::endl << std::endl;
    std::cout << "A=" << A << ";" << std::endl << std::endl;
  } catch (const std::exception& e) {
    std::cerr << "Cought exception " << e.what();
    std::cerr << "in the main function of access-tensor." << std::endl;
  }

  try {
    using value   = std::complex<boost::multiprecision::cpp_bin_float_double_extended>;
    using layout  = ublas::layout::last_order; // storage format
    using tensor  = ublas::tensor_dynamic<value,layout>;
    using shape   = typename tensor::extents_type;
    constexpr auto zeros = ublas::zeros<value,layout>{};

    // creates a four-dimensional tensor with extents 5,4,3 and 2
    // tensor A stores complex floating-point extended double precision numbers
    // according to the last-order storage format
    // and initializes it with the default value.

    //NOLINTNEXTLINE
    tensor B = zeros(5,4,3,2);

    // initializes the tensor with increasing values along the last-index
    // using a single-index
    auto vc = value(0,0);
    for(auto i = 0u; i < B.size(); ++i, vc += value(1,1))
      B[i] = vc;

    // formatted output
    std::cout << "% --------------------------- " << std::endl;
    std::cout << "% --------------------------- " << std::endl << std::endl;
    std::cout << "B=" << B << ";" << std::endl << std::endl;

    auto C = tensor(B.extents());
    // computes the complex conjugate of elements of B
    // using multi-index notation.
    for(auto i = 0u; i < B.size(0); ++i)
      for(auto j = 0u; j < B.size(1); ++j)
        for(auto k = 0u; k < B.size(2); ++k)
          for(auto l = 0u; l < B.size(3); ++l)
            C.at(i,j,k,l) = std::conj(B.at(i,j,k,l));

    std::cout << "% --------------------------- " << std::endl;
    std::cout << "% --------------------------- " << std::endl << std::endl;
    std::cout << "C=" << C << ";" << std::endl << std::endl;

    // computes the complex conjugate of elements of B
    // using iterators.
    auto D = tensor(B.extents());
    std::transform(B.begin(), B.end(), D.begin(), [](auto const& b){ return std::conj(b); });
    std::cout << "% --------------------------- " << std::endl;
    std::cout << "% --------------------------- " << std::endl << std::endl;
    std::cout << "D=" << D << ";" << std::endl << std::endl;

    // reshaping tensors.
    auto new_extents = B.extents().base();
    std::next_permutation( new_extents.begin(), new_extents.end() );
    auto E = reshape( D, shape(new_extents)  );
    std::cout << "% --------------------------- " << std::endl;
    std::cout << "% --------------------------- " << std::endl << std::endl;
    std::cout << "E=" << E << ";" << std::endl << std::endl;

  } catch (const std::exception& e) {
    std::cerr << "Cought exception " << e.what();
    std::cerr << "in the main function of access-tensor." << std::endl;
  }
}


#include "integration.hpp"
#include <iostream>
#include <Eigen/Sparse>
#include <Eigen/IterativeLinearSolvers>
using namespace std;

void explicitEulerStep(PhysicalSystem *system, double dt) {
    forwardEulerStep(system, dt);
}

void forwardEulerStep(PhysicalSystem *system, double dt) {
    int n = system->getDOFs();
    VectorXd x0(n), v0(n);
    system->getState(x0, v0);
    MatrixXd M(n,n);
    system->getInertia(M);
    VectorXd f0(n);
    system->getForces(f0);
    VectorXd a0(n); // acceleration
    for (int i = 0; i < n; i++)
        a0(i) = f0(i)/M(i,i);
    VectorXd x1 = x0 + v0*dt;
    VectorXd v1 = v0 + a0*dt;
    system->setState(x1, v1);
}

VectorXd solve(const MatrixXd &A, const VectorXd &b) {
    SparseMatrix<double> spA = A.sparseView();
    ConjugateGradient< SparseMatrix<double> > solver;
    solver.setTolerance(1e-3);
    return solver.compute(spA).solve(b);
}

void backwardEulerStep(PhysicalSystem *system, double dt) {
    int n = system->getDOFs();
    VectorXd x0(n), v0(n);
    system->getState(x0, v0);
    static MatrixXd M(n,n);
    system->getInertia(M);
    VectorXd f(n);
    static MatrixXd Jx(n,n), Jv(n,n);
    system->getForces(f);
    system->getJacobians(Jx, Jv);
    MatrixXd A = (M - Jx*dt*dt - Jv*dt);
    VectorXd b = (f + Jx*v0*dt)*dt;
    VectorXd v1 = v0 + solve(A, b);
    system->setState(x0 + v1*dt, v1);
}