<commit_before>/**
* @version		GrPPI v0.2
* @copyright		Copyright (C) 2017 Universidad Carlos III de Madrid. All rights reserved.
* @license		GNU/GPL, see LICENSE.txt
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You have received a copy of the GNU General Public License in LICENSE.txt
* also available in <http://www.gnu.org/licenses/gpl.html>.
*
* See COPYRIGHT.txt for copyright notices and details.
*/

#include <atomic>
#include <experimental/optional>
#include <numeric>

#include <gtest/gtest.h>

#include "grppi.h"
#include "dyn/dynamic_execution.h"

#include "supported_executions.h"

using namespace std;
using namespace grppi;
template <typename T>
using optional = std::experimental::optional<T>;

template <typename T>
class context_test : public ::testing::Test {
public:
  T execution_;
  dynamic_execution dyn_execution_{execution_};
  sequential_execution seq_;
  parallel_execution_native thr_;
#ifdef GRPPI_OMP
  parallel_execution_omp omp_;
#endif
  parallel_execution_tbb tbb_;

  // Variables
  int out;
  int counter;

  // Vectors
  vector<int> v{};
  vector<vector<int> > v2{};

  // Invocation counter
  std::atomic<int> invocations_init{0};
  std::atomic<int> invocations_last{0};
  std::atomic<int> invocations_intermediate{0};
  std::atomic<int> invocations_intermediate2{0};

  void setup_three_stages() {
    counter = 5;
    out = 0;
  }

  template <typename E>
  void run_three_stages_farm_with_sequential(const E & e) {
    grppi::pipeline(e,
      [this,i=0,max=counter]() mutable -> optional<int> {
        invocations_init++;
        if (++i<=max) return i;
        else return {};
      },
      grppi::run_with(this->seq_,
        grppi::farm(2,
          [this](int x) {
            invocations_intermediate++;
            return x*2;
          }
        )
      ),
      [this](int x) {
        invocations_last++;
        out += x;
      });
  }

  template <typename E>
  void run_three_stages_farm_with_native(const E & e) {
    grppi::pipeline(e,
      [this,i=0,max=counter]() mutable -> optional<int> {
        invocations_init++;
        if (++i<=max) return i;
        else return {};
      },
      grppi::run_with(this->thr_,
        grppi::farm(2,
          [this](int x) {
            invocations_intermediate++;
            return x*2;
          }
        )
      ),
      [this](int x) {
        invocations_last++;
        out += x;
      });
  }

  template <typename E>
  void run_three_stages_farm_with_omp(const E & e) {
    grppi::pipeline(e,
      [this,i=0,max=counter]() mutable -> optional<int> {
        invocations_init++;
        if (++i<=max) return i;
        else return {};
      },
#ifdef GRPPI_OMP
      grppi::run_with(this->omp_,
        grppi::farm(2,
          [this](int x) {
            invocations_intermediate++;
            return x*2;
          }
        )
      ),
#endif
      [this](int x) {
        invocations_last++;
        out += x;
      });
  }

  template <typename E>
  void run_three_stages_farm_with_tbb(const E & e) {
    grppi::pipeline(e,
      [this,i=0,max=counter]() mutable -> optional<int> {
        invocations_init++;
        if (++i<=max) return i;
        else return {};
      },
      grppi::run_with(this->tbb_,
        grppi::farm(2,
          [this](int x) {
            invocations_intermediate++;
            return x*2;
          }
        )
      ),
      [this](int x) {
        invocations_last++;
        out += x;
      });
  }
  void check_three_stages() {
    EXPECT_EQ(6, invocations_init);
    EXPECT_EQ(5, invocations_last);
    EXPECT_EQ(5, invocations_intermediate);
    EXPECT_EQ(0, invocations_intermediate2);
    EXPECT_EQ(30, out);
  }

  void setup_composed() {
    counter = 5;
    out = 0;
  }

  template <typename E>
  void run_composed_pipeline_with_sequential(const E & e) {
    grppi::pipeline(e,
      [this,i=0,max=counter]() mutable -> optional<int> {
        invocations_init++;
        if (++i<=max) return i;
        else return {};
      },
      grppi::run_with(this->seq_,
        grppi::pipeline(
          [this](int x) {
            std::cerr << "squaring " << x << std::endl;
            invocations_intermediate++;
            std::cerr << "Incrementing\n";
            return x*x;
          },
          [this](int x) {
            invocations_intermediate2++;
            x *= 2;
            return x;
          }
        )
      ),
      [this](int x) {
          invocations_last++;
          out +=x;
      });
  }

  template <typename E>
  void run_composed_pipeline_with_native(const E & e) {
    grppi::pipeline(e,
      [this,i=0,max=counter]() mutable -> optional<int> {
        invocations_init++;
        if (++i<=max) return i;
        else return {};
      },
      grppi::run_with(this->thr_,
        grppi::pipeline(
          [this](int x) {
            std::cerr << "squaring " << x << std::endl;
            invocations_intermediate++;
            std::cerr << "Incrementing\n";
            return x*x;
          },
          [this](int x) {
            invocations_intermediate2++;
            x *= 2;
            return x;
          }
        )
      ),
      [this](int x) {
          invocations_last++;
          out +=x;
      });
  }

  template <typename E>
  void run_composed_pipeline_with_omp(const E & e) {
    grppi::pipeline(e,
      [this,i=0,max=counter]() mutable -> optional<int> {
        invocations_init++;
        if (++i<=max) return i;
        else return {};
      },
#ifdef GRPPI_OMP
      grppi::run_with(this->omp_,
        grppi::pipeline(
          [this](int x) {
            std::cerr << "squaring " << x << std::endl;
            invocations_intermediate++;
            std::cerr << "Incrementing\n";
            return x*x;
          },
          [this](int x) {
            invocations_intermediate2++;
            x *= 2;
            return x;
          }
        )
      ),
#endif
      [this](int x) {
          invocations_last++;
          out +=x;
      });
  }

  template <typename E>
  void run_composed_pipeline_with_tbb(const E & e) {
    grppi::pipeline(e,
      [this,i=0,max=counter]() mutable -> optional<int> {
        invocations_init++;
        if (++i<=max) return i;
        else return {};
      },
      grppi::run_with(this->tbb_,
        grppi::pipeline(
          [this](int x) {
            std::cerr << "squaring " << x << std::endl;
            invocations_intermediate++;
            std::cerr << "Incrementing\n";
            return x*x;
          },
          [this](int x) {
            invocations_intermediate2++;
            x *= 2;
            return x;
          }
        )
      ),
      [this](int x) {
          invocations_last++;
          out +=x;
      });
  }

  void check_composed() {
    EXPECT_EQ(6, invocations_init);
    EXPECT_EQ(5, invocations_last);
    EXPECT_EQ(5, invocations_intermediate);
    EXPECT_EQ(5, invocations_intermediate2);
    EXPECT_EQ(110, out);
  }

};

// Test for execution policies defined in supported_executions.h
TYPED_TEST_CASE(context_test, executions_noff);

TYPED_TEST(context_test, static_three_stages_farm_seq)
{
  this->setup_three_stages();
  this->run_three_stages_farm_with_sequential(this->execution_);
  this->check_three_stages();
}

TYPED_TEST(context_test, static_three_stages_farm_nat)
{
  this->setup_three_stages();
  this->run_three_stages_farm_with_native(this->execution_);
  this->check_three_stages();
}

#ifdef GRPPI_OMP
TYPED_TEST(context_test, static_three_stages_farm_omp)
{
  this->setup_three_stages();
  this->run_three_stages_farm_with_omp(this->execution_);
  this->check_three_stages();
}
#endif

TYPED_TEST(context_test, static_three_stages_farm_tbb)
{
  this->setup_three_stages();
  this->run_three_stages_farm_with_tbb(this->execution_);
  this->check_three_stages();
}

TYPED_TEST(context_test, dyn_three_stages_farm_seq)
{
  this->setup_three_stages();
  this->run_three_stages_farm_with_sequential(this->dyn_execution_);
  this->check_three_stages();
}

TYPED_TEST(context_test, dyn_three_stages_farm_nat)
{
  this->setup_three_stages();
  this->run_three_stages_farm_with_native(this->dyn_execution_);
  this->check_three_stages();
}

#ifdef GRPPI_OMP
TYPED_TEST(context_test, dyn_three_stages_farm_omp)
{
  this->setup_three_stages();
  this->run_three_stages_farm_with_omp(this->dyn_execution_);
  this->check_three_stages();
}
#endif

TYPED_TEST(context_test, dyn_three_stages_farm_tbb)
{
  this->setup_three_stages();
  this->run_three_stages_farm_with_tbb(this->dyn_execution_);
  this->check_three_stages();
}

TYPED_TEST(context_test, static_composed_pipeline_seq)
{
  this->setup_composed();
  this->run_composed_pipeline_with_sequential(this->execution_);
  this->check_composed();
}

TYPED_TEST(context_test, static_composed_pipeline_nat)
{
  this->setup_composed();
  this->run_composed_pipeline_with_native(this->execution_);
  this->check_composed();
}

#ifdef GRPPI_OMP
TYPED_TEST(context_test, static_composed_pipeline_omp)
{
  this->setup_composed();
  this->run_composed_pipeline_with_omp(this->execution_);
  this->check_composed();
}
#endif

TYPED_TEST(context_test, static_composed_pipeline_tbb)
{
  this->setup_composed();
  this->run_composed_pipeline_with_tbb(this->execution_);
  this->check_composed();
}

TYPED_TEST(context_test, dyn_composed_pipeline_seq)
{
  this->setup_composed();
  this->run_composed_pipeline_with_sequential(this->dyn_execution_);
  this->check_composed();
}

TYPED_TEST(context_test, dyn_composed_pipeline_nat)
{
  this->setup_composed();
  this->run_composed_pipeline_with_native(this->dyn_execution_);
  this->check_composed();
}

#ifdef GRPPI_OMP
TYPED_TEST(context_test, dyn_composed_pipeline_omp)
{
  this->setup_composed();
  this->run_composed_pipeline_with_omp(this->dyn_execution_);
  this->check_composed();
}
#endif

TYPED_TEST(context_test, dyn_composed_pipeline_tbb)
{
  this->setup_composed();
  this->run_composed_pipeline_with_tbb(this->dyn_execution_);
  this->check_composed();
}
<commit_msg>Conditionally support testing of TBB<commit_after>/**
* @version		GrPPI v0.2
* @copyright		Copyright (C) 2017 Universidad Carlos III de Madrid. All rights reserved.
* @license		GNU/GPL, see LICENSE.txt
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You have received a copy of the GNU General Public License in LICENSE.txt
* also available in <http://www.gnu.org/licenses/gpl.html>.
*
* See COPYRIGHT.txt for copyright notices and details.
*/

#include <atomic>
#include <experimental/optional>
#include <numeric>

#include <gtest/gtest.h>

#include "grppi.h"
#include "dyn/dynamic_execution.h"

#include "supported_executions.h"

using namespace std;
using namespace grppi;
template <typename T>
using optional = std::experimental::optional<T>;

template <typename T>
class context_test : public ::testing::Test {
public:
  T execution_;
  dynamic_execution dyn_execution_{execution_};
  sequential_execution seq_;
  parallel_execution_native thr_;
#ifdef GRPPI_OMP
  parallel_execution_omp omp_;
#endif
#ifdef GRPPI_TBB
  parallel_execution_tbb tbb_;
#endif

  // Variables
  int out;
  int counter;

  // Vectors
  vector<int> v{};
  vector<vector<int> > v2{};

  // Invocation counter
  std::atomic<int> invocations_init{0};
  std::atomic<int> invocations_last{0};
  std::atomic<int> invocations_intermediate{0};
  std::atomic<int> invocations_intermediate2{0};

  void setup_three_stages() {
    counter = 5;
    out = 0;
  }

  template <typename E>
  void run_three_stages_farm_with_sequential(const E & e) {
    grppi::pipeline(e,
      [this,i=0,max=counter]() mutable -> optional<int> {
        invocations_init++;
        if (++i<=max) return i;
        else return {};
      },
      grppi::run_with(this->seq_,
        grppi::farm(2,
          [this](int x) {
            invocations_intermediate++;
            return x*2;
          }
        )
      ),
      [this](int x) {
        invocations_last++;
        out += x;
      });
  }

  template <typename E>
  void run_three_stages_farm_with_native(const E & e) {
    grppi::pipeline(e,
      [this,i=0,max=counter]() mutable -> optional<int> {
        invocations_init++;
        if (++i<=max) return i;
        else return {};
      },
      grppi::run_with(this->thr_,
        grppi::farm(2,
          [this](int x) {
            invocations_intermediate++;
            return x*2;
          }
        )
      ),
      [this](int x) {
        invocations_last++;
        out += x;
      });
  }

  template <typename E>
  void run_three_stages_farm_with_omp(const E & e) {
    grppi::pipeline(e,
      [this,i=0,max=counter]() mutable -> optional<int> {
        invocations_init++;
        if (++i<=max) return i;
        else return {};
      },
#ifdef GRPPI_OMP
      grppi::run_with(this->omp_,
        grppi::farm(2,
          [this](int x) {
            invocations_intermediate++;
            return x*2;
          }
        )
      ),
#endif
      [this](int x) {
        invocations_last++;
        out += x;
      });
  }

  template <typename E>
  void run_three_stages_farm_with_tbb(const E & e) {
    grppi::pipeline(e,
      [this,i=0,max=counter]() mutable -> optional<int> {
        invocations_init++;
        if (++i<=max) return i;
        else return {};
      },
#ifdef GRPPI_TBB
      grppi::run_with(this->tbb_,
        grppi::farm(2,
          [this](int x) {
            invocations_intermediate++;
            return x*2;
          }
        )
      ),
#endif
      [this](int x) {
        invocations_last++;
        out += x;
      });
  }
  void check_three_stages() {
    EXPECT_EQ(6, invocations_init);
    EXPECT_EQ(5, invocations_last);
    EXPECT_EQ(5, invocations_intermediate);
    EXPECT_EQ(0, invocations_intermediate2);
    EXPECT_EQ(30, out);
  }

  void setup_composed() {
    counter = 5;
    out = 0;
  }

  template <typename E>
  void run_composed_pipeline_with_sequential(const E & e) {
    grppi::pipeline(e,
      [this,i=0,max=counter]() mutable -> optional<int> {
        invocations_init++;
        if (++i<=max) return i;
        else return {};
      },
      grppi::run_with(this->seq_,
        grppi::pipeline(
          [this](int x) {
            std::cerr << "squaring " << x << std::endl;
            invocations_intermediate++;
            std::cerr << "Incrementing\n";
            return x*x;
          },
          [this](int x) {
            invocations_intermediate2++;
            x *= 2;
            return x;
          }
        )
      ),
      [this](int x) {
          invocations_last++;
          out +=x;
      });
  }

  template <typename E>
  void run_composed_pipeline_with_native(const E & e) {
    grppi::pipeline(e,
      [this,i=0,max=counter]() mutable -> optional<int> {
        invocations_init++;
        if (++i<=max) return i;
        else return {};
      },
      grppi::run_with(this->thr_,
        grppi::pipeline(
          [this](int x) {
            std::cerr << "squaring " << x << std::endl;
            invocations_intermediate++;
            std::cerr << "Incrementing\n";
            return x*x;
          },
          [this](int x) {
            invocations_intermediate2++;
            x *= 2;
            return x;
          }
        )
      ),
      [this](int x) {
          invocations_last++;
          out +=x;
      });
  }

  template <typename E>
  void run_composed_pipeline_with_omp(const E & e) {
    grppi::pipeline(e,
      [this,i=0,max=counter]() mutable -> optional<int> {
        invocations_init++;
        if (++i<=max) return i;
        else return {};
      },
#ifdef GRPPI_OMP
      grppi::run_with(this->omp_,
        grppi::pipeline(
          [this](int x) {
            std::cerr << "squaring " << x << std::endl;
            invocations_intermediate++;
            std::cerr << "Incrementing\n";
            return x*x;
          },
          [this](int x) {
            invocations_intermediate2++;
            x *= 2;
            return x;
          }
        )
      ),
#endif
      [this](int x) {
          invocations_last++;
          out +=x;
      });
  }

  template <typename E>
  void run_composed_pipeline_with_tbb(const E & e) {
    grppi::pipeline(e,
      [this,i=0,max=counter]() mutable -> optional<int> {
        invocations_init++;
        if (++i<=max) return i;
        else return {};
      },
#ifdef GRPPI_TBB
      grppi::run_with(this->tbb_,
        grppi::pipeline(
          [this](int x) {
            std::cerr << "squaring " << x << std::endl;
            invocations_intermediate++;
            std::cerr << "Incrementing\n";
            return x*x;
          },
          [this](int x) {
            invocations_intermediate2++;
            x *= 2;
            return x;
          }
        )
      ),
#endif
      [this](int x) {
          invocations_last++;
          out +=x;
      });
  }

  void check_composed() {
    EXPECT_EQ(6, invocations_init);
    EXPECT_EQ(5, invocations_last);
    EXPECT_EQ(5, invocations_intermediate);
    EXPECT_EQ(5, invocations_intermediate2);
    EXPECT_EQ(110, out);
  }

};

// Test for execution policies defined in supported_executions.h
TYPED_TEST_CASE(context_test, executions_noff);

TYPED_TEST(context_test, static_three_stages_farm_seq)
{
  this->setup_three_stages();
  this->run_three_stages_farm_with_sequential(this->execution_);
  this->check_three_stages();
}

TYPED_TEST(context_test, static_three_stages_farm_nat)
{
  this->setup_three_stages();
  this->run_three_stages_farm_with_native(this->execution_);
  this->check_three_stages();
}

#ifdef GRPPI_OMP
TYPED_TEST(context_test, static_three_stages_farm_omp)
{
  this->setup_three_stages();
  this->run_three_stages_farm_with_omp(this->execution_);
  this->check_three_stages();
}
#endif

#ifdef GRPPI_TBB
TYPED_TEST(context_test, static_three_stages_farm_tbb)
{
  this->setup_three_stages();
  this->run_three_stages_farm_with_tbb(this->execution_);
  this->check_three_stages();
}
#endif

TYPED_TEST(context_test, dyn_three_stages_farm_seq)
{
  this->setup_three_stages();
  this->run_three_stages_farm_with_sequential(this->dyn_execution_);
  this->check_three_stages();
}

TYPED_TEST(context_test, dyn_three_stages_farm_nat)
{
  this->setup_three_stages();
  this->run_three_stages_farm_with_native(this->dyn_execution_);
  this->check_three_stages();
}

#ifdef GRPPI_OMP
TYPED_TEST(context_test, dyn_three_stages_farm_omp)
{
  this->setup_three_stages();
  this->run_three_stages_farm_with_omp(this->dyn_execution_);
  this->check_three_stages();
}
#endif

#ifdef GRPPI_TBB
TYPED_TEST(context_test, dyn_three_stages_farm_tbb)
{
  this->setup_three_stages();
  this->run_three_stages_farm_with_tbb(this->dyn_execution_);
  this->check_three_stages();
}
#endif

TYPED_TEST(context_test, static_composed_pipeline_seq)
{
  this->setup_composed();
  this->run_composed_pipeline_with_sequential(this->execution_);
  this->check_composed();
}

TYPED_TEST(context_test, static_composed_pipeline_nat)
{
  this->setup_composed();
  this->run_composed_pipeline_with_native(this->execution_);
  this->check_composed();
}

#ifdef GRPPI_OMP
TYPED_TEST(context_test, static_composed_pipeline_omp)
{
  this->setup_composed();
  this->run_composed_pipeline_with_omp(this->execution_);
  this->check_composed();
}
#endif

#ifdef GRPPI_TBB
TYPED_TEST(context_test, static_composed_pipeline_tbb)
{
  this->setup_composed();
  this->run_composed_pipeline_with_tbb(this->execution_);
  this->check_composed();
}
#endif

TYPED_TEST(context_test, dyn_composed_pipeline_seq)
{
  this->setup_composed();
  this->run_composed_pipeline_with_sequential(this->dyn_execution_);
  this->check_composed();
}

TYPED_TEST(context_test, dyn_composed_pipeline_nat)
{
  this->setup_composed();
  this->run_composed_pipeline_with_native(this->dyn_execution_);
  this->check_composed();
}

#ifdef GRPPI_OMP
TYPED_TEST(context_test, dyn_composed_pipeline_omp)
{
  this->setup_composed();
  this->run_composed_pipeline_with_omp(this->dyn_execution_);
  this->check_composed();
}
#endif

#ifdef GRPPI_TBB
TYPED_TEST(context_test, dyn_composed_pipeline_tbb)
{
  this->setup_composed();
  this->run_composed_pipeline_with_tbb(this->dyn_execution_);
  this->check_composed();
}
#endif
<|endoftext|>


<commit_before>#define DEBUG 1
/**
 * File    : D2.cpp
 * Author  : Kazune Takahashi
 * Created : 2020/3/9 17:08:58
 * 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++() { return *this += 1; }
  Mint &operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint &operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  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; }
// ----- for C++17 -----
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}; // or
// constexpr int infty{1'000'000'010};
// 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() -----

using shop = tuple<ll, ll>;

ostream &operator<<(ostream &os, shop const &s)
{
  return os << "(" << get<0>(s) << ", " << get<1>(s) << ")";
}

class Solve
{
  static constexpr int C{32};
  int N, M, L;
  ll T;
  vector<shop> V;
  vector<shop> normal, zero;
  vector<ll> sum;
  vector<vector<ll>> dp;

public:
  Solve(int N, ll T, vector<shop> V) : N{N}, T{T}, V(V)
  {
    make_normal_zero();
    execute_dp();
    cout << calc_ans() << endl;
  }

private:
  static bool compare_normal(shop const &left, shop const &right)
  {
    return (get<0>(right) - 1) * get<1>(left) - (get<0>(left) - 1) * get<1>(right) < 0;
  }

  static bool compare_zero(shop const &left, shop const &right)
  {
    return get<1>(left) < get<1>(right);
  }

  ll f(int i, ll x)
  {
    return get<0>(normal[i]) * x + get<1>(normal[i]);
  }

  void make_normal_zero()
  {
    for (auto i = 0; i < N; ++i)
    {
      if (get<0>(V[i]) >= 2)
      {
        normal.push_back(V[i]);
      }
      else
      {
        zero.push_back(V[i]);
      }
    }
    M = normal.size();
    L = zero.size();
    sort(normal.begin(), normal.end(), compare_normal);
    sort(zero.begin(), zero.end(), compare_zero);
    exit(0);
    sum = vector<ll>(L + 1, 0);
    for (auto i = 0; i < L; ++i)
    {
      sum[i + 1] = sum[i] + get<1>(zero[i]);
    }
  }

  void execute_dp()
  {
    dp = vector<vector<ll>>(M + 1, vector<ll>(C, infty));
    dp[0][0] = 0;
    for (auto i = 0; i < M; ++i)
    {
      dp[i + 1][0] = dp[i][0];
      for (auto j = 1; j < C; ++j)
      {
        dp[i + 1][j] = min(dp[i][j], f(i, dp[i][j - 1]));
      }
    }
  }

  int calc_ans()
  {
    int ans{0};
    for (auto i = 0; i < C; ++i)
    {
      ll remain{T - dp[M][i]};
      if (remain < 0)
      {
        continue;
      }
      int z{static_cast<int>(upper_bound(sum.begin(), sum.end(), remain) - sum.begin()) - 1};
      ch_max(ans, z + i);
    }
    return ans;
  }
};

int main()
{
  int N;
  ll T;
  cin >> N >> T;
  vector<shop> V(N);
  for (auto i = 0; i < N; ++i)
  {
    ll a, b;
    cin >> a >> b;
    V[i] = shop(a + 1, a + b + 1);
  }
  Solve solve(N, T, V);
}
<commit_msg>submit D2.cpp to 'D - Manga Market' (hitachi2020) [C++14 (GCC 5.4.1)]<commit_after>#define DEBUG 1
/**
 * File    : D2.cpp
 * Author  : Kazune Takahashi
 * Created : 2020/3/9 17:08:58
 * 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++() { return *this += 1; }
  Mint &operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint &operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  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; }
// ----- for C++17 -----
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}; // or
// constexpr int infty{1'000'000'010};
// 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() -----

using shop = tuple<ll, ll>;

ostream &operator<<(ostream &os, shop const &s)
{
  return os << "(" << get<0>(s) << ", " << get<1>(s) << ")";
}

class Solve
{
  static constexpr int C{32};
  int N, M, L;
  ll T;
  vector<shop> V;
  vector<shop> normal, zero;
  vector<ll> sum;
  vector<vector<ll>> dp;

public:
  Solve(int N, ll T, vector<shop> V) : N{N}, T{T}, V(V)
  {
    make_normal_zero();
    execute_dp();
    cout << calc_ans() << endl;
  }

private:
  static bool compare_normal(shop const &left, shop const &right)
  {
    return (get<0>(right) - 1) * get<1>(left) - (get<0>(left) - 1) * get<1>(right) < 0;
  }

  static bool compare_zero(shop const &left, shop const &right)
  {
    return get<1>(left) < get<1>(right);
  }

  ll f(int i, ll x)
  {
    return get<0>(normal[i]) * x + get<1>(normal[i]);
  }

  void make_normal_zero()
  {
    for (auto i = 0; i < N; ++i)
    {
      if (get<0>(V[i]) >= 2)
      {
        normal.push_back(V[i]);
      }
      else
      {
        zero.push_back(V[i]);
      }
    }
    M = normal.size();
    L = zero.size();
    sort(normal.begin(), normal.end(), compare_normal);
    sort(zero.begin(), zero.end(), compare_zero);
    sum = vector<ll>(L + 1, 0);
    for (auto i = 0; i < L; ++i)
    {
      sum[i + 1] = sum[i] + get<1>(zero[i]);
    }
  }

  void execute_dp()
  {
    dp = vector<vector<ll>>(M + 1, vector<ll>(C, infty));
    dp[0][0] = 0;
    for (auto i = 0; i < M; ++i)
    {
      dp[i + 1][0] = dp[i][0];
      for (auto j = 1; j < C; ++j)
      {
        dp[i + 1][j] = min(dp[i][j], f(i, dp[i][j - 1]));
      }
    }
  }

  int calc_ans()
  {
    int ans{0};
    for (auto i = 0; i < C; ++i)
    {
      ll remain{T - dp[M][i]};
      if (remain < 0)
      {
        continue;
      }
      int z{static_cast<int>(upper_bound(sum.begin(), sum.end(), remain) - sum.begin()) - 1};
      ch_max(ans, z + i);
    }
    return ans;
  }
};

int main()
{
  int N;
  ll T;
  cin >> N >> T;
  vector<shop> V(N);
  for (auto i = 0; i < N; ++i)
  {
    ll a, b;
    cin >> a >> b;
    V[i] = shop(a + 1, a + b + 1);
  }
  Solve solve(N, T, V);
}
<|endoftext|>


<commit_before>#include "Commands.h"
#include <unistd.h>
#include <sys/wait.h>

static const int STDIN_FD  = 0;
static const int STDOUT_FD = 1;

Atomic::Atomic(const std::vector<std::string>& cmdline, const std::vector<Redirection*>& redirections, bool _background) :
    _cmdline(cmdline), _redirections(redirections), _background(_background) {}

int Atomic::run() {
    if(_cmdline.empty()) {
        return 0;
    //} else if(_cmdline.front() == "cd") {
    } else {
        int oldstdin = dup(STDIN_FD);
        int oldstdout = dup(STDOUT_FD);
        for(Redirection* r : _redirections) {
            r->doRedirection();
        }

        pid_t pid = fork();
        if(pid == 0) {
            std::vector<char*> argv;
            argv.reserve(_cmdline.size()+1);
            std::string commandPath = "/usr/bin/" + _cmdline[0];
            for(size_t i = 0; i < _cmdline.size(); ++i) {
                argv.push_back(const_cast<char*>(_cmdline[i].data()));
            }
            argv.push_back(nullptr);
            execv(commandPath.data(), reinterpret_cast<char * const *>(argv.data()));
            return 42; //make gcc happy
        } else {
            int res;
            wait(&res);
            dup2(oldstdin, STDIN_FD);
            dup2(oldstdout, STDOUT_FD);
            close(oldstdin);
            close(oldstdout);
            return res;
        }
    }
}

If::If(Command* cond, Command* ifcommand, Command* elsecommand) :
    _cond(cond), _ifcommand(ifcommand), _elsecommand(elsecommand) {}

int If::run() {
    int condres = _cond->run();
    if(condres == 0) {
        return _ifcommand->run();
    } else {
        return _elsecommand->run();
    }
}

Pipe::Pipe(Command* producer, Command* consumer) :
    _producer(producer), _consumer(consumer) {}

int Pipe::run() {
    int pipes[2];
    if(pipe(pipes) != 0) {
        perror("pipe");
        return -1;
    }
    int pipeout = pipes[0];
    int pipein = pipes[1];

    pid_t pid = fork();
    if(pid == 0) {
        //producer
        dup2(pipein, STDOUT_FD);
        close(pipeout);
        close(pipein);
        _producer->run();
        exit(0);
    } else {
        //consumer
        int oldstdin = dup(STDIN_FD);
        dup2(pipeout, STDIN_FD);
        close(pipein);
        close(pipeout);
        int res = _consumer->run();
        wait(nullptr);
        dup2(oldstdin, STDIN_FD);
        close(oldstdin);
        return res;
    }
}

And::And(Command* command1, Command* command2) :
    _command1(command1), _command2(command2) {}

int And::run() {
    int res1 = _command1->run();
    if(res1 == 0) {
        return _command2->run();
    } else {
        return res1;
    }
}

Or::Or(Command* command1, Command* command2) :
    _command1(command1), _command2(command2) {}

int Or::run() {
    int res1 = _command1->run();
    if(res1 != 0) {
        return _command2->run();
    } else {
        return res1;
    }
}

Seq::Seq(Command* command1, Command* command2) :
    _command1(command1), _command2(command2) {}

int Seq::run() {
    _command1->run();
    return _command2->run();
}

<commit_msg>Improve ttsh<commit_after>#include "Commands.h"
#include <unistd.h>
#include <sys/wait.h>

static const int STDIN_FD  = 0;
static const int STDOUT_FD = 1;

Atomic::Atomic(const std::vector<std::string>& cmdline, const std::vector<Redirection*>& redirections, bool _background) :
    _cmdline(cmdline), _redirections(redirections), _background(_background) {}

int Atomic::run() {
    if(_cmdline.empty()) {
        return 0;
    //} else if(_cmdline.front() == "cd") {
    } else {
        int oldstdin = dup(STDIN_FD);
        int oldstdout = dup(STDOUT_FD);
        for(Redirection* r : _redirections) {
            r->doRedirection();
        }

        pid_t pid = fork();
        if(pid == 0) {
            std::vector<char*> argv;
            argv.reserve(_cmdline.size()+1);
            bool hasSlash = false;
            for(size_t i = 0; i < _cmdline[0].size(); ++i) {
                hasSlash |= (_cmdline[0][i] == '/');
            }
            std::string commandPath = hasSlash ? _cmdline[0] : ("/usr/bin/" + _cmdline[0]);
            for(size_t i = 0; i < _cmdline.size(); ++i) {
                argv.push_back(const_cast<char*>(_cmdline[i].data()));
            }
            argv.push_back(nullptr);
            if(execv(commandPath.data(), reinterpret_cast<char * const *>(argv.data()))) {
                perror("execv");
                return -1;
            }
            return 42; //make gcc happy
        } else {
            int res;
            wait(&res);
            dup2(oldstdin, STDIN_FD);
            dup2(oldstdout, STDOUT_FD);
            close(oldstdin);
            close(oldstdout);
            return res;
        }
    }
}

If::If(Command* cond, Command* ifcommand, Command* elsecommand) :
    _cond(cond), _ifcommand(ifcommand), _elsecommand(elsecommand) {}

int If::run() {
    int condres = _cond->run();
    if(condres == 0) {
        return _ifcommand->run();
    } else {
        return _elsecommand->run();
    }
}

Pipe::Pipe(Command* producer, Command* consumer) :
    _producer(producer), _consumer(consumer) {}

int Pipe::run() {
    int pipes[2];
    if(pipe(pipes) != 0) {
        perror("pipe");
        return -1;
    }
    int pipeout = pipes[0];
    int pipein = pipes[1];

    pid_t pid = fork();
    if(pid == 0) {
        //producer
        dup2(pipein, STDOUT_FD);
        close(pipeout);
        close(pipein);
        _producer->run();
        exit(0);
    } else {
        //consumer
        int oldstdin = dup(STDIN_FD);
        dup2(pipeout, STDIN_FD);
        close(pipein);
        close(pipeout);
        int res = _consumer->run();
        wait(nullptr);
        dup2(oldstdin, STDIN_FD);
        close(oldstdin);
        return res;
    }
}

And::And(Command* command1, Command* command2) :
    _command1(command1), _command2(command2) {}

int And::run() {
    int res1 = _command1->run();
    if(res1 == 0) {
        return _command2->run();
    } else {
        return res1;
    }
}

Or::Or(Command* command1, Command* command2) :
    _command1(command1), _command2(command2) {}

int Or::run() {
    int res1 = _command1->run();
    if(res1 != 0) {
        return _command2->run();
    } else {
        return res1;
    }
}

Seq::Seq(Command* command1, Command* command2) :
    _command1(command1), _command2(command2) {}

int Seq::run() {
    _command1->run();
    return _command2->run();
}

<|endoftext|>


<commit_before>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2015
Raffaello D. Di Napoli

This file is part of Abaclade.

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

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

You should have received a copy of the GNU General Public License along with Abaclade. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#ifndef _ABACLADE_COLLECTIONS_DETAIL_TRIE_ORDERED_MULTIMAP_HXX
#define _ABACLADE_COLLECTIONS_DETAIL_TRIE_ORDERED_MULTIMAP_HXX

#ifndef _ABACLADE_HXX
   #error "Please #include <abaclade.hxx> before this file"
#endif
#ifdef ABC_CXX_PRAGMA_ONCE
   #pragma once
#endif

#include <abaclade/collections/type_void_adapter.hxx>
#include <abaclade/numeric.hxx>

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace abc { namespace collections { namespace detail {

//! Implementation of abc::collections::trie_ordered_multimap for scalar key types.
class ABACLADE_SYM scalar_keyed_trie_ordered_multimap_impl {
private:
   /*! Determines the compactness of each level of the tree. Packing multiple bits on each level
   results in faster lookups and fewer memory allocations, at the cost of increased slack in each
   tree node. */
   static unsigned const smc_cBitsPerLevel = 4;
   //! Count of children pointers that each tree node needs.
   static unsigned const smc_cBitPermutationsPerLevel = 1 << smc_cBitsPerLevel;
   static unsigned const smc_iTreeAnchorLevel =
      sizeof(std::uintmax_t /*TODO: TKey*/) * 8 /*TODO: CHAR_BIT*/ / smc_cBitsPerLevel - 1;

protected:
   /*! Abstract node. Defined to avoid using void * in code where pointers’ type change depending on
   the level in the tree. */
   class node {
   };

   //! Stores a single value, as well as the doubly-linked list’s links.
   class list_node : public node {
   public:
      //! Constructor.
      list_node() :
         m_plnNext(nullptr),
         m_plnPrev(nullptr) {
      }

      void unlink_and_destruct(type_void_adapter const & type) const;

      /*! Returns a pointer to the contained value.

      @param type
         Adapter for the value’s type.
      @return
         Pointer to the contained value.
      */
      void * value_ptr(type_void_adapter const & type) const;

      /*! Returns a typed pointer to the contained TValue.

      @return
         Pointer to the contained value.
      */
      template <typename TValue>
      TValue * value_ptr() const {
         type_void_adapter typeValue;
         typeValue.set_align<TValue>();
         return static_cast<TValue *>(value_ptr(typeValue));
      }

   public:
      //! Pointer to the next node.
      list_node * m_plnNext;
      //! Pointer to the previous node.
      list_node * m_plnPrev;
      // The contained value of type T follow immediately, taking alignment into consideration.
   };

   //! Non-leaf node.
   class tree_node : public node {
   public:
      //! Constructor.
      tree_node() {
         memory::clear(&m_apnChildren);
      }

   public:
      //! Child prefix pointers; one for each permutation of the bits mapped to this tree node.
      node * m_apnChildren[smc_cBitPermutationsPerLevel];
   };

   //! Anchors value lists to the tree, mapping the last bits of the key.
   class anchor_node : public tree_node {
   public:
      //! Constructor.
      anchor_node() {
         memory::clear(&m_aplnChildrenLasts);
      }

   public:
      //! Child lists end pointers; one for each permutation of the bits mapped to this tree node.
      list_node * m_aplnChildrenLasts[smc_cBitPermutationsPerLevel];
   };

   struct indexed_anchor {
      anchor_node * pan;
      unsigned iBitsPermutation;

      indexed_anchor(anchor_node * _pan, unsigned _iBitsPermutation) :
         pan(_pan),
         iBitsPermutation(_iBitsPermutation) {
      }
   };

   //! Key/pointer-to-value pair.
   struct key_value_pair {
      std::uintmax_t iKey;
      list_node * pln;

      key_value_pair(std::uintmax_t _iKey, list_node * _pln) :
         iKey(_iKey),
         pln(_pln) {
      }
   };

public:
   /*! Constructor.

   @param tommi
      Source object.
   */
   scalar_keyed_trie_ordered_multimap_impl() :
      m_pnRoot(nullptr),
      m_cValues(0) {
   }
   scalar_keyed_trie_ordered_multimap_impl(scalar_keyed_trie_ordered_multimap_impl && tommi);

   //! Destructor.
   ~scalar_keyed_trie_ordered_multimap_impl() {
   }

   /*! Adds a key/value pair to the map.

   @param typeValue
      Adapter for the value’s type.
   @param iKey
      Key to add.
   @param value
      Value to add.
   @param bMove
      true to move *pValue to the new node’s value, or false to copy it instead.
   @return
      Pointer to the newly-added list node.
   */
   list_node * add(
      type_void_adapter const & typeValue, std::uintmax_t iKey, void const * pValue, bool bMove
   );

   /*! Removes all elements from the map.

   @param typeValue
      Adapter for the value’s type.
   */
   void clear(type_void_adapter const & typeValue);

   /*! Returns true if the map contains no elements.

   @return
      true if the map is empty, or false otherwise.
   */
   bool empty() const {
      return m_cValues == 0;
   }

   /*! Searches the multimap for a specific key, returning a pointer to the first corresponding list
   node if found.

   @param iKey
      Key to search for.
   @return
      Pointer to the to the first matching list node, or nullptr if the key could not be found.
   */
   list_node * find(std::uintmax_t iKey);

   /*! Returns a pointer to the first value in the map.

   @return
      Pointer to the first value in the map.
   */
   key_value_pair front();

   /*! Returns the count of values in the map. Note that this may be higher than the count of keys
   in the map.

   @return
      Count of values.
   */
   std::size_t size() const {
      return m_cValues;
   }

protected:
   void remove_value(type_void_adapter const & typeValue, std::uintmax_t iKey, list_node * pln);

private:
   indexed_anchor descend_to_anchor(std::uintmax_t iKey) const;

   void destruct_list(type_void_adapter const & type, list_node * pln);

   void destruct_anchor_node(type_void_adapter const & typeValue, anchor_node * pan);

   void destruct_tree_node(type_void_adapter const & typeValue, tree_node * ptn, unsigned iLevel);

private:
   /*! Pointer to the top-level node. The type should be tree_node *, but some code requires this to
   be the same as tree_node::m_apnChildren[0]. */
   node * m_pnRoot;
   //! Count of values. This may be more than the count of keys.
   std::size_t m_cValues;
};

}}} //namespace abc::collections::detail

////////////////////////////////////////////////////////////////////////////////////////////////////

#endif //ifndef _ABACLADE_COLLECTIONS_DETAIL_TRIE_ORDERED_MULTIMAP_HXX
<commit_msg>Use CHAR_BIT instead of 8<commit_after>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2015
Raffaello D. Di Napoli

This file is part of Abaclade.

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

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

You should have received a copy of the GNU General Public License along with Abaclade. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#ifndef _ABACLADE_COLLECTIONS_DETAIL_TRIE_ORDERED_MULTIMAP_HXX
#define _ABACLADE_COLLECTIONS_DETAIL_TRIE_ORDERED_MULTIMAP_HXX

#ifndef _ABACLADE_HXX
   #error "Please #include <abaclade.hxx> before this file"
#endif
#ifdef ABC_CXX_PRAGMA_ONCE
   #pragma once
#endif

#include <abaclade/collections/type_void_adapter.hxx>
#include <abaclade/numeric.hxx>

#include <climits> // CHAR_BIT

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace abc { namespace collections { namespace detail {

//! Implementation of abc::collections::trie_ordered_multimap for scalar key types.
class ABACLADE_SYM scalar_keyed_trie_ordered_multimap_impl {
private:
   /*! Determines the compactness of each level of the tree. Packing multiple bits on each level
   results in faster lookups and fewer memory allocations, at the cost of increased slack in each
   tree node. */
   static unsigned const smc_cBitsPerLevel = 4;
   //! Count of children pointers that each tree node needs.
   static unsigned const smc_cBitPermutationsPerLevel = 1 << smc_cBitsPerLevel;
   static unsigned const smc_iTreeAnchorLevel =
      sizeof(std::uintmax_t /*TODO: TKey*/) * CHAR_BIT / smc_cBitsPerLevel - 1;

protected:
   /*! Abstract node. Defined to avoid using void * in code where pointers’ type change depending on
   the level in the tree. */
   class node {
   };

   //! Stores a single value, as well as the doubly-linked list’s links.
   class list_node : public node {
   public:
      //! Constructor.
      list_node() :
         m_plnNext(nullptr),
         m_plnPrev(nullptr) {
      }

      void unlink_and_destruct(type_void_adapter const & type) const;

      /*! Returns a pointer to the contained value.

      @param type
         Adapter for the value’s type.
      @return
         Pointer to the contained value.
      */
      void * value_ptr(type_void_adapter const & type) const;

      /*! Returns a typed pointer to the contained TValue.

      @return
         Pointer to the contained value.
      */
      template <typename TValue>
      TValue * value_ptr() const {
         type_void_adapter typeValue;
         typeValue.set_align<TValue>();
         return static_cast<TValue *>(value_ptr(typeValue));
      }

   public:
      //! Pointer to the next node.
      list_node * m_plnNext;
      //! Pointer to the previous node.
      list_node * m_plnPrev;
      // The contained value of type T follow immediately, taking alignment into consideration.
   };

   //! Non-leaf node.
   class tree_node : public node {
   public:
      //! Constructor.
      tree_node() {
         memory::clear(&m_apnChildren);
      }

   public:
      //! Child prefix pointers; one for each permutation of the bits mapped to this tree node.
      node * m_apnChildren[smc_cBitPermutationsPerLevel];
   };

   //! Anchors value lists to the tree, mapping the last bits of the key.
   class anchor_node : public tree_node {
   public:
      //! Constructor.
      anchor_node() {
         memory::clear(&m_aplnChildrenLasts);
      }

   public:
      //! Child lists end pointers; one for each permutation of the bits mapped to this tree node.
      list_node * m_aplnChildrenLasts[smc_cBitPermutationsPerLevel];
   };

   struct indexed_anchor {
      anchor_node * pan;
      unsigned iBitsPermutation;

      indexed_anchor(anchor_node * _pan, unsigned _iBitsPermutation) :
         pan(_pan),
         iBitsPermutation(_iBitsPermutation) {
      }
   };

   //! Key/pointer-to-value pair.
   struct key_value_pair {
      std::uintmax_t iKey;
      list_node * pln;

      key_value_pair(std::uintmax_t _iKey, list_node * _pln) :
         iKey(_iKey),
         pln(_pln) {
      }
   };

public:
   /*! Constructor.

   @param tommi
      Source object.
   */
   scalar_keyed_trie_ordered_multimap_impl() :
      m_pnRoot(nullptr),
      m_cValues(0) {
   }
   scalar_keyed_trie_ordered_multimap_impl(scalar_keyed_trie_ordered_multimap_impl && tommi);

   //! Destructor.
   ~scalar_keyed_trie_ordered_multimap_impl() {
   }

   /*! Adds a key/value pair to the map.

   @param typeValue
      Adapter for the value’s type.
   @param iKey
      Key to add.
   @param value
      Value to add.
   @param bMove
      true to move *pValue to the new node’s value, or false to copy it instead.
   @return
      Pointer to the newly-added list node.
   */
   list_node * add(
      type_void_adapter const & typeValue, std::uintmax_t iKey, void const * pValue, bool bMove
   );

   /*! Removes all elements from the map.

   @param typeValue
      Adapter for the value’s type.
   */
   void clear(type_void_adapter const & typeValue);

   /*! Returns true if the map contains no elements.

   @return
      true if the map is empty, or false otherwise.
   */
   bool empty() const {
      return m_cValues == 0;
   }

   /*! Searches the multimap for a specific key, returning a pointer to the first corresponding list
   node if found.

   @param iKey
      Key to search for.
   @return
      Pointer to the to the first matching list node, or nullptr if the key could not be found.
   */
   list_node * find(std::uintmax_t iKey);

   /*! Returns a pointer to the first value in the map.

   @return
      Pointer to the first value in the map.
   */
   key_value_pair front();

   /*! Returns the count of values in the map. Note that this may be higher than the count of keys
   in the map.

   @return
      Count of values.
   */
   std::size_t size() const {
      return m_cValues;
   }

protected:
   void remove_value(type_void_adapter const & typeValue, std::uintmax_t iKey, list_node * pln);

private:
   indexed_anchor descend_to_anchor(std::uintmax_t iKey) const;

   void destruct_list(type_void_adapter const & type, list_node * pln);

   void destruct_anchor_node(type_void_adapter const & typeValue, anchor_node * pan);

   void destruct_tree_node(type_void_adapter const & typeValue, tree_node * ptn, unsigned iLevel);

private:
   /*! Pointer to the top-level node. The type should be tree_node *, but some code requires this to
   be the same as tree_node::m_apnChildren[0]. */
   node * m_pnRoot;
   //! Count of values. This may be more than the count of keys.
   std::size_t m_cValues;
};

}}} //namespace abc::collections::detail

////////////////////////////////////////////////////////////////////////////////////////////////////

#endif //ifndef _ABACLADE_COLLECTIONS_DETAIL_TRIE_ORDERED_MULTIMAP_HXX
<|endoftext|>


<commit_before>/** @file iterativeSolvers.cpp

    @brief Example on how the solve a system of linear equation with the MINRES and CG method.

    This file is part of the G+Smo library.

    This Source Code Form is subject to the terms of the Mozilla Public
    License, v. 2.0. If a copy of the MPL was not distributed with this
    file, You can obtain one at http://mozilla.org/MPL/2.0/.

    Author(s): J. Sogn
*/

#include <iostream>
#include <gismo.h>

using std::cout;
using std::endl;
using namespace gismo;

int main(int argc, char *argv[])
{
    //Size of linear system
    index_t N = 200;
    if (argc >= 2)
        N = atoi(argv[1]);

    gsMatrix<> mat;
    gsMatrix<> rhs;

    mat.setZero(N,N);
    rhs.setRandom(N,1);

    //Create a tri-diagonal matrix with -1 of the off diagonals and 2 in the diagonal.
    //This matrix is equivalent to discretizing the 1D Poisson equation with homogenius
    //Dirichlet boundary condition using a finit difference schema. It is a SPD matrix.
    mat(0,0) = 2;
    mat(0,1) = -1;
    mat(N-1, N-1) = 2;
    mat(N-1, N-2) = -1;
    for (index_t k = 1; k < N-1; ++k)
    {
        mat(k,k) = 2;
        mat(k,k-1) = -1;
        mat(k,k+1) = -1;
    }

    //The minimal residual implementation requires a preconditioner.
    //We initialize an Identity preconditioner (does nothing).
    gsIdentityPreconditioner preConMat(N);

    //Set maximum number of iterations
    index_t maxIters = 1000;
    //Set tolerance
    real_t tol = 1e-08;

    //Initialize the MinRes solver
    gsMinimalResidual MinRes(mat,maxIters,tol);

    //Create the initial guess
    gsMatrix<> x0;
    x0.setZero(N,1);

    //Solve system with given preconditioner (solution is stored in x0)
    gsInfo << "MinRes: Before solve"  << std::endl;
    MinRes.solve(rhs,x0,preConMat);
    gsInfo << "MinRes: After solve"  << std::endl;

    gsInfo << "MinRes: Solved a system of size " << N << "\n";
    gsInfo << "MinRes: Tolerance: " << tol << "\n";
    gsInfo << "MinRes: Residual error: " << MinRes.error() << "\n";
    gsInfo << "MinRes: Number of iterations: " << MinRes.iterations() << "\n";

    //Initialize the CG solver
    gsConjugateGradient CGSolver(mat,maxIters,tol);

    //Set the initial guess to zero
    x0.setZero(N,1);

    //Solve system with given preconditioner (solution is stored in x0)
    gsInfo << "\nCG: Before solve"  << std::endl;
    CGSolver.solve(rhs,x0,preConMat);
    gsInfo << "CG: After solve"  << std::endl;

    gsInfo << "CG: Solved a system of size " << N << "\n";
    gsInfo << "CG: Tolerance: " << tol << "\n";
    gsInfo << "CG: Residual error: " << CGSolver.error() << "\n";
    gsInfo << "CG: Number of iterations: " << CGSolver.iterations() << "\n";

    int result = (MinRes.error()<tol)?0:1;
    result += (CGSolver.error()<tol)?0:1;
    return result;
}
<commit_msg>Updated example to include GMRes<commit_after>/** @file iterativeSolvers.cpp

    @brief Example on how the solve a system of linear equation with the MINRES and CG method.

    This file is part of the G+Smo library.

    This Source Code Form is subject to the terms of the Mozilla Public
    License, v. 2.0. If a copy of the MPL was not distributed with this
    file, You can obtain one at http://mozilla.org/MPL/2.0/.

    Author(s): J. Sogn
*/

#include <iostream>
#include <gismo.h>

using std::cout;
using std::endl;
using namespace gismo;

int main(int argc, char *argv[])
{
    //Size of linear system
    index_t N = 200;
    if (argc >= 2)
        N = atoi(argv[1]);

    gsMatrix<> mat;
    gsMatrix<> rhs;

    mat.setZero(N,N);
    rhs.setRandom(N,1);

    //Create a tri-diagonal matrix with -1 of the off diagonals and 2 in the diagonal.
    //This matrix is equivalent to discretizing the 1D Poisson equation with homogenius
    //Dirichlet boundary condition using a finit difference schema. It is a SPD matrix.
    mat(0,0) = 2;
    mat(0,1) = -1;
    mat(N-1, N-1) = 2;
    mat(N-1, N-2) = -1;
    for (index_t k = 1; k < N-1; ++k)
    {
        mat(k,k) = 2;
        mat(k,k-1) = -1;
        mat(k,k+1) = -1;
    }

    //The minimal residual implementation requires a preconditioner.
    //We initialize an Identity preconditioner (does nothing).
    gsIdentityPreconditioner preConMat(N);

    //Set maximum number of iterations
    index_t maxIters = 1000;
    //Set tolerance
    real_t tol = 1e-08;

    //Initialize the MinRes solver
    gsMinimalResidual MinRes(mat,maxIters,tol);

    //Create the initial guess
    gsMatrix<> x0;
    x0.setZero(N,1);

    //Solve system with given preconditioner (solution is stored in x0)
    gsInfo << "\nMinRes: Before solve"  << std::endl;
    MinRes.solve(rhs,x0,preConMat);
    gsInfo << "MinRes: After solve"  << std::endl;

    gsInfo << "MinRes: Solved a system of size " << N << "\n";
    gsInfo << "MinRes: Tolerance: " << tol << "\n";
    gsInfo << "MinRes: Residual error: " << MinRes.error() << "\n";
    gsInfo << "MinRes: Number of iterations: " << MinRes.iterations() << "\n";

    //Initialize the CG solver
    gsGMRes GMResSolver(mat,maxIters,tol);

    //Set the initial guess to zero
    x0.setZero(N,1);

    //Solve system with given preconditioner (solution is stored in x0)
    gsInfo << "\nGMRes: Before solve"  << std::endl;
    GMResSolver.solve(rhs,x0,preConMat);
    gsInfo << "GMRes: After solve"  << std::endl;

    gsInfo << "GMRes: Solved a system of size " << N << "\n";
    gsInfo << "GMRes: Tolerance: " << tol << "\n";
    gsInfo << "GMRes: Residual error: " << GMResSolver.error() << "\n";
    gsInfo << "GMRes: Number of iterations: " << GMResSolver.iterations() << "\n";

    //Initialize the CG solver
    gsConjugateGradient CGSolver(mat,maxIters,tol);

    //Set the initial guess to zero
    x0.setZero(N,1);

    //Solve system with given preconditioner (solution is stored in x0)
    gsInfo << "\nCG: Before solve"  << std::endl;
    CGSolver.solve(rhs,x0,preConMat);
    gsInfo << "CG: After solve"  << std::endl;

    gsInfo << "CG: Solved a system of size " << N << "\n";
    gsInfo << "CG: Tolerance: " << tol << "\n";
    gsInfo << "CG: Residual error: " << CGSolver.error() << "\n";
    gsInfo << "CG: Number of iterations: " << CGSolver.iterations() << "\n";

    int result = (MinRes.error()<tol)?0:1;
    result += (CGSolver.error()<tol)?0:1;
    return result;
}
<|endoftext|>


<commit_before>#include <gtest/gtest.h>
#include <exception>
#include <algorithm>

#include <iostream>
using std::endl ;

#include <vector>
using std::vector ;

#include <sofa/helper/logging/Messaging.h>
using sofa::helper::logging::MessageDispatcher ;

#include <sofa/helper/logging/MessageHandler.h>
using sofa::helper::logging::MessageHandler ;

#include <sofa/helper/logging/Message.h>
using sofa::helper::logging::Message ;

#include <sofa/core/objectmodel/BaseObject.h>
#include <sofa/core/ObjectFactory.h>

class MyMessageHandler : public MessageHandler
{
    vector<Message> m_messages ;
public:
    virtual void process(Message& m){
        m_messages.push_back(m);

        if( !m.sender().empty() )
            std::cerr<<m<<std::endl;
    }

    int numMessages(){
        return m_messages.size() ;
    }

    const vector<Message>& messages() const {
        return m_messages;
    }
    const Message& lastMessage() const {
        return m_messages.back();
    }
} ;

class MyComponent : public sofa::core::objectmodel::BaseObject
{
public:
    SOFA_CLASS( MyComponent, sofa::core::objectmodel::BaseObject );
    MyComponent()
    {
        f_printLog.setValue(true); // to print sout
        serr<<"regular serr"<<sendl;
        sout<<"regular sout"<<sendl;
        serr<<SOFA_FILE_INFO<<"serr with fileinfo"<<sendl;
        sout<<SOFA_FILE_INFO<<"sout with fileinfo"<<sendl;
    }
};

SOFA_DECL_CLASS(MyComponent)
int MyComponentClass = sofa::core::RegisterObject("MyComponent")
        .add< MyComponent >();

TEST(LoggingTest, noHandler)
{
    MessageDispatcher::clearHandlers() ;

    msg_info("") << " info message with conversion" << 1.5 << "\n" ;
    msg_warning("") << " warning message with conversion "<< 1.5 << "\n" ;
    msg_error("") << " error message with conversion" << 1.5 << "\n" ;
}

TEST(LoggingTest, oneHandler)
{
    MessageDispatcher::clearHandlers() ;

    MyMessageHandler h;

    // add is expected to return the handler ID. Here is it the o'th
    EXPECT_TRUE(MessageDispatcher::addHandler(&h) == 0 ) ;

    msg_info("") << " info message with conversion" << 1.5 << "\n" ;
    msg_warning("") << " warning message with conversion "<< 1.5 << "\n" ;
    msg_error("") << " error message with conversion" << 1.5 << "\n" ;

    EXPECT_TRUE( h.numMessages() == 3 ) ;
}

TEST(LoggingTest, duplicatedHandler)
{
    MessageDispatcher::clearHandlers() ;

    MyMessageHandler h;

    // First add is expected to return the handler ID.
    EXPECT_TRUE(MessageDispatcher::addHandler(&h) == 0) ;

    // Second is supposed to fail to add and thus return -1.
    EXPECT_TRUE(MessageDispatcher::addHandler(&h) == -1) ;

    msg_info("") << " info message with conversion" << 1.5 << "\n" ;
    msg_warning("") << " warning message with conversion "<< 1.5 << "\n" ;
    msg_error("") << " error message with conversion" << 1.5 << "\n" ;

    EXPECT_TRUE( h.numMessages() == 3) ;
}

TEST(LoggingTest, withoutDevMode)
{
    MessageDispatcher::clearHandlers() ;

    MyMessageHandler h;
    MessageDispatcher::addHandler(&h) ;

    msg_info("") << " info message with conversion" << 1.5 << "\n" ;
    msg_warning("") << " warning message with conversion "<< 1.5 << "\n" ;
    msg_error("") << " error message with conversion" << 1.5 << "\n" ;

    nmsg_info("") << " null info message with conversion" << 1.5 << "\n" ;
    nmsg_warning("") << " null warning message with conversion "<< 1.5 << "\n" ;
    nmsg_error("") << " null error message with conversion" << 1.5 << "\n" ;

    EXPECT_TRUE( h.numMessages() == 3 ) ;
}

//TEST(LoggingTest, speedTest)
//{
//    MessageDispatcher::clearHandlers() ;

//    MyMessageHandler h;
//    MessageDispatcher::addHandler(&h) ;

//    for(unsigned int i=0;i<10000;i++){
//        msg_info("") << " info message with conversion" << 1.5 << "\n" ;
//        msg_warning("") << " warning message with conversion "<< 1.5 << "\n" ;
//        msg_error("") << " error message with conversion" << 1.5 << "\n" ;
//    }
//}

TEST(LoggingTest, BaseObject)
{
    MessageDispatcher::clearHandlers() ;
    MyMessageHandler h;
    MessageDispatcher::addHandler(&h) ;

    MyComponent c;
    EXPECT_EQ( h.numMessages(), 4 ) ;

    if( h.numMessages() < 4 ) return; // not to crash

    c.serr<<"regular external serr"<<c.sendl;
    EXPECT_EQ( h.lastMessage().fileInfo().line, 0 );
    EXPECT_TRUE( !strcmp( h.lastMessage().fileInfo().filename, sofa::helper::logging::s_unknownFile ) );
    EXPECT_EQ( h.lastMessage().type(), sofa::helper::logging::Message::Warning );

    c.serr<<sofa::helper::logging::Message::Error<<"external serr as Error"<<c.sendl;
    EXPECT_EQ( h.lastMessage().fileInfo().line, 0 );
    EXPECT_TRUE( !strcmp( h.lastMessage().fileInfo().filename, sofa::helper::logging::s_unknownFile ) );
    EXPECT_EQ( h.lastMessage().type(), sofa::helper::logging::Message::Error );

    c.sout<<"regular external sout"<<c.sendl;
    EXPECT_EQ( h.lastMessage().fileInfo().line, 0 );
    EXPECT_TRUE( !strcmp( h.lastMessage().fileInfo().filename, sofa::helper::logging::s_unknownFile ) );
    EXPECT_EQ( h.lastMessage().type(), sofa::helper::logging::Message::Info );

    c.sout<<sofa::helper::logging::Message::Error<<"external sout as Error"<<c.sendl;
    EXPECT_EQ( h.lastMessage().fileInfo().line, 0 );
    EXPECT_TRUE( !strcmp( h.lastMessage().fileInfo().filename, sofa::helper::logging::s_unknownFile ) );
    EXPECT_EQ( h.lastMessage().type(), sofa::helper::logging::Message::Error );

    c.serr<<SOFA_FILE_INFO<<"external serr with fileinfo"<<c.sendl;
    EXPECT_EQ( h.lastMessage().fileInfo().line, __LINE__-1 );
    EXPECT_TRUE( !strcmp( h.lastMessage().fileInfo().filename, __FILE__ ) );

    c.sout<<SOFA_FILE_INFO<<"external sout with fileinfo"<<c.sendl;
    EXPECT_EQ( h.lastMessage().fileInfo().line, __LINE__-1 );
    EXPECT_TRUE( !strcmp( h.lastMessage().fileInfo().filename, __FILE__ ) );

    c.serr<<SOFA_FILE_INFO<<sofa::helper::logging::Message::Error<<"external serr as Error with fileinfo"<<c.sendl;
    EXPECT_EQ( h.lastMessage().fileInfo().line, __LINE__-1 );
    EXPECT_TRUE( !strcmp( h.lastMessage().fileInfo().filename, __FILE__ ) );
    EXPECT_EQ( h.lastMessage().type(), sofa::helper::logging::Message::Error );

    c.sout<<sofa::helper::logging::Message::Error<<SOFA_FILE_INFO<<"external sout as Error with fileinfo"<<c.sendl;
    EXPECT_EQ( h.lastMessage().fileInfo().line, __LINE__-1 );
    EXPECT_TRUE( !strcmp( h.lastMessage().fileInfo().filename, __FILE__ ) );
    EXPECT_EQ( h.lastMessage().type(), sofa::helper::logging::Message::Error );

    c.serr<<"serr with sendl that comes in a second time";
    c.serr<<c.sendl;
    EXPECT_EQ( h.lastMessage().fileInfo().line, 0 );
    EXPECT_TRUE( !strcmp( h.lastMessage().fileInfo().filename, sofa::helper::logging::s_unknownFile ) );
    EXPECT_EQ( h.lastMessage().type(), sofa::helper::logging::Message::Warning );

    c.serr<<"\n serr with \n end of "<<std::endl<<" lines"<<c.sendl;
    EXPECT_EQ( h.lastMessage().fileInfo().line, 0 );
    EXPECT_TRUE( !strcmp( h.lastMessage().fileInfo().filename, sofa::helper::logging::s_unknownFile ) );
    EXPECT_EQ( h.lastMessage().type(), sofa::helper::logging::Message::Warning );

    EXPECT_EQ( h.numMessages(), 14 ) ;
}

#undef MESSAGING_H
#define WITH_SOFA_DEVTOOLS
#undef dmsg_info
#undef dmsg_error
#undef dmsg_warning
#undef dmsg_fatal
#include <sofa/helper/logging/Messaging.h>

TEST(LoggingTest, withDevMode)
{
    MessageDispatcher::clearHandlers() ;

    MyMessageHandler h;
    MessageDispatcher::addHandler(&h) ;

    msg_info("") << " info message with conversion" << 1.5 << "\n" ;
    msg_warning("") << " warning message with conversion "<< 1.5 << "\n" ;
    msg_error("") << " error message with conversion" << 1.5 << "\n" ;

    nmsg_info("") << " null info message with conversion" << 1.5 << "\n" ;
    nmsg_warning("") << " null warning message with conversion "<< 1.5 << "\n" ;
    nmsg_error("") << " null error message with conversion" << 1.5 << "\n" ;

    dmsg_info("") << " debug info message with conversion" << 1.5 << "\n" ;
    dmsg_warning("") << " debug warning message with conversion "<< 1.5 << "\n" ;
    dmsg_error("") << " debug error message with conversion" << 1.5 << "\n" ;

    EXPECT_TRUE( h.numMessages() == 6 ) ;
}
<commit_msg>[logger] a bit more details on the failing test<commit_after>#include <gtest/gtest.h>
#include <exception>
#include <algorithm>

#include <iostream>
using std::endl ;

#include <vector>
using std::vector ;

#include <sofa/helper/logging/Messaging.h>
using sofa::helper::logging::MessageDispatcher ;

#include <sofa/helper/logging/MessageHandler.h>
using sofa::helper::logging::MessageHandler ;

#include <sofa/helper/logging/Message.h>
using sofa::helper::logging::Message ;

#include <sofa/core/objectmodel/BaseObject.h>
#include <sofa/core/ObjectFactory.h>

class MyMessageHandler : public MessageHandler
{
    vector<Message> m_messages ;
public:
    virtual void process(Message& m){
        m_messages.push_back(m);

        if( !m.sender().empty() )
            std::cerr<<m<<std::endl;
    }

    int numMessages(){
        return m_messages.size() ;
    }

    const vector<Message>& messages() const {
        return m_messages;
    }
    const Message& lastMessage() const {
        return m_messages.back();
    }
} ;

class MyComponent : public sofa::core::objectmodel::BaseObject
{
public:
    SOFA_CLASS( MyComponent, sofa::core::objectmodel::BaseObject );
    MyComponent()
    {
        f_printLog.setValue(true); // to print sout
        serr<<"regular serr"<<sendl;
        sout<<"regular sout"<<sendl;
        serr<<SOFA_FILE_INFO<<"serr with fileinfo"<<sendl;
        sout<<SOFA_FILE_INFO<<"sout with fileinfo"<<sendl;
    }
};

SOFA_DECL_CLASS(MyComponent)
int MyComponentClass = sofa::core::RegisterObject("MyComponent")
        .add< MyComponent >();

TEST(LoggingTest, noHandler)
{
    MessageDispatcher::clearHandlers() ;

    msg_info("") << " info message with conversion" << 1.5 << "\n" ;
    msg_warning("") << " warning message with conversion "<< 1.5 << "\n" ;
    msg_error("") << " error message with conversion" << 1.5 << "\n" ;
}

TEST(LoggingTest, oneHandler)
{
    MessageDispatcher::clearHandlers() ;

    MyMessageHandler h;

    // add is expected to return the handler ID. Here is it the o'th
    EXPECT_TRUE(MessageDispatcher::addHandler(&h) == 0 ) ;

    msg_info("") << " info message with conversion" << 1.5 << "\n" ;
    msg_warning("") << " warning message with conversion "<< 1.5 << "\n" ;
    msg_error("") << " error message with conversion" << 1.5 << "\n" ;

    EXPECT_TRUE( h.numMessages() == 3 ) ;
}

TEST(LoggingTest, duplicatedHandler)
{
    MessageDispatcher::clearHandlers() ;

    MyMessageHandler h;

    // First add is expected to return the handler ID.
    EXPECT_TRUE(MessageDispatcher::addHandler(&h) == 0) ;

    // Second is supposed to fail to add and thus return -1.
    EXPECT_TRUE(MessageDispatcher::addHandler(&h) == -1) ;

    msg_info("") << " info message with conversion" << 1.5 << "\n" ;
    msg_warning("") << " warning message with conversion "<< 1.5 << "\n" ;
    msg_error("") << " error message with conversion" << 1.5 << "\n" ;

    EXPECT_TRUE( h.numMessages() == 3) ;
}

TEST(LoggingTest, withoutDevMode)
{
    MessageDispatcher::clearHandlers() ;

    MyMessageHandler h;
    MessageDispatcher::addHandler(&h) ;

    msg_info("") << " info message with conversion" << 1.5 << "\n" ;
    msg_warning("") << " warning message with conversion "<< 1.5 << "\n" ;
    msg_error("") << " error message with conversion" << 1.5 << "\n" ;

    nmsg_info("") << " null info message with conversion" << 1.5 << "\n" ;
    nmsg_warning("") << " null warning message with conversion "<< 1.5 << "\n" ;
    nmsg_error("") << " null error message with conversion" << 1.5 << "\n" ;

    EXPECT_TRUE( h.numMessages() == 3 ) ;
}

//TEST(LoggingTest, speedTest)
//{
//    MessageDispatcher::clearHandlers() ;

//    MyMessageHandler h;
//    MessageDispatcher::addHandler(&h) ;

//    for(unsigned int i=0;i<10000;i++){
//        msg_info("") << " info message with conversion" << 1.5 << "\n" ;
//        msg_warning("") << " warning message with conversion "<< 1.5 << "\n" ;
//        msg_error("") << " error message with conversion" << 1.5 << "\n" ;
//    }
//}

TEST(LoggingTest, BaseObject)
{
    MessageDispatcher::clearHandlers() ;
    MyMessageHandler h;
    MessageDispatcher::addHandler(&h) ;

    MyComponent c; /// the constructor is sending 4 messages
    EXPECT_EQ( h.numMessages(), 4 ) ;

    if( h.numMessages() == 4 ) // not to crash
    {
        c.serr<<"regular external serr"<<c.sendl;
        EXPECT_EQ( h.lastMessage().fileInfo().line, 0 );
        EXPECT_TRUE( !strcmp( h.lastMessage().fileInfo().filename, sofa::helper::logging::s_unknownFile ) );
        EXPECT_EQ( h.lastMessage().type(), sofa::helper::logging::Message::Warning );

        c.serr<<sofa::helper::logging::Message::Error<<"external serr as Error"<<c.sendl;
        EXPECT_EQ( h.lastMessage().fileInfo().line, 0 );
        EXPECT_TRUE( !strcmp( h.lastMessage().fileInfo().filename, sofa::helper::logging::s_unknownFile ) );
        EXPECT_EQ( h.lastMessage().type(), sofa::helper::logging::Message::Error );

        c.sout<<"regular external sout"<<c.sendl;
        EXPECT_EQ( h.lastMessage().fileInfo().line, 0 );
        EXPECT_TRUE( !strcmp( h.lastMessage().fileInfo().filename, sofa::helper::logging::s_unknownFile ) );
        EXPECT_EQ( h.lastMessage().type(), sofa::helper::logging::Message::Info );

        c.sout<<sofa::helper::logging::Message::Error<<"external sout as Error"<<c.sendl;
        EXPECT_EQ( h.lastMessage().fileInfo().line, 0 );
        EXPECT_TRUE( !strcmp( h.lastMessage().fileInfo().filename, sofa::helper::logging::s_unknownFile ) );
        EXPECT_EQ( h.lastMessage().type(), sofa::helper::logging::Message::Error );
    }

    c.serr<<SOFA_FILE_INFO<<"external serr with fileinfo"<<c.sendl;
    EXPECT_EQ( h.lastMessage().fileInfo().line, __LINE__-1 );
    EXPECT_TRUE( !strcmp( h.lastMessage().fileInfo().filename, __FILE__ ) );

    c.sout<<SOFA_FILE_INFO<<"external sout with fileinfo"<<c.sendl;
    EXPECT_EQ( h.lastMessage().fileInfo().line, __LINE__-1 );
    EXPECT_TRUE( !strcmp( h.lastMessage().fileInfo().filename, __FILE__ ) );

    c.serr<<SOFA_FILE_INFO<<sofa::helper::logging::Message::Error<<"external serr as Error with fileinfo"<<c.sendl;
    EXPECT_EQ( h.lastMessage().fileInfo().line, __LINE__-1 );
    EXPECT_TRUE( !strcmp( h.lastMessage().fileInfo().filename, __FILE__ ) );
    EXPECT_EQ( h.lastMessage().type(), sofa::helper::logging::Message::Error );

    c.sout<<sofa::helper::logging::Message::Error<<SOFA_FILE_INFO<<"external sout as Error with fileinfo"<<c.sendl;
    EXPECT_EQ( h.lastMessage().fileInfo().line, __LINE__-1 );
    EXPECT_TRUE( !strcmp( h.lastMessage().fileInfo().filename, __FILE__ ) );
    EXPECT_EQ( h.lastMessage().type(), sofa::helper::logging::Message::Error );

    c.serr<<"serr with sendl that comes in a second time";
    c.serr<<c.sendl;
    EXPECT_EQ( h.lastMessage().fileInfo().line, 0 );
    EXPECT_TRUE( !strcmp( h.lastMessage().fileInfo().filename, sofa::helper::logging::s_unknownFile ) );
    EXPECT_EQ( h.lastMessage().type(), sofa::helper::logging::Message::Warning );

    c.serr<<"\n serr with \n end of "<<std::endl<<" lines"<<c.sendl;
    EXPECT_EQ( h.lastMessage().fileInfo().line, 0 );
    EXPECT_TRUE( !strcmp( h.lastMessage().fileInfo().filename, sofa::helper::logging::s_unknownFile ) );
    EXPECT_EQ( h.lastMessage().type(), sofa::helper::logging::Message::Warning );

    EXPECT_EQ( h.numMessages(), 14 ) ;
}

#undef MESSAGING_H
#define WITH_SOFA_DEVTOOLS
#undef dmsg_info
#undef dmsg_error
#undef dmsg_warning
#undef dmsg_fatal
#include <sofa/helper/logging/Messaging.h>

TEST(LoggingTest, withDevMode)
{
    MessageDispatcher::clearHandlers() ;

    MyMessageHandler h;
    MessageDispatcher::addHandler(&h) ;

    msg_info("") << " info message with conversion" << 1.5 << "\n" ;
    msg_warning("") << " warning message with conversion "<< 1.5 << "\n" ;
    msg_error("") << " error message with conversion" << 1.5 << "\n" ;

    nmsg_info("") << " null info message with conversion" << 1.5 << "\n" ;
    nmsg_warning("") << " null warning message with conversion "<< 1.5 << "\n" ;
    nmsg_error("") << " null error message with conversion" << 1.5 << "\n" ;

    dmsg_info("") << " debug info message with conversion" << 1.5 << "\n" ;
    dmsg_warning("") << " debug warning message with conversion "<< 1.5 << "\n" ;
    dmsg_error("") << " debug error message with conversion" << 1.5 << "\n" ;

    EXPECT_TRUE( h.numMessages() == 6 ) ;
}
<|endoftext|>


<commit_before>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "AddSideSetsFromBoundingBox.h"
#include "Conversion.h"
#include "MooseMesh.h"
#include "MooseTypes.h"

registerMooseObject("MooseApp", AddSideSetsFromBoundingBox);

template <>
InputParameters
validParams<AddSideSetsFromBoundingBox>()
{
  InputParameters params = validParams<MeshModifier>();
  params.addClassDescription("Find sidesets with given boundary ids in bounding box and add new "
                             "boundary id. This can be done by finding all required boundary "
                             "and adding the new boundary id to those sidesets. Alternatively, "
                             "a number of boundary ids can be provided and all nodes within the "
                             "bounding box that have all the required boundary ids will have a new"
                             "boundary id added.");

  MooseEnum location("INSIDE OUTSIDE", "INSIDE");

  params.addRequiredParam<RealVectorValue>(
      "bottom_left", "The bottom left point (in x,y,z with spaces in-between).");
  params.addRequiredParam<RealVectorValue>(
      "top_right", "The bottom left point (in x,y,z with spaces in-between).");
  params.addRequiredParam<SubdomainID>("block_id",
                                       "Subdomain id to set for inside/outside the bounding box");
  params.addRequiredParam<std::vector<BoundaryName>>(
      "boundary_id_old", "Boundary id on specified block within the bounding box to select");
  params.addRequiredParam<boundary_id_type>(
      "boundary_id_new", "Boundary id on specified block within the bounding box to assign");
  params.addParam<bool>("boundary_id_overlap",
                        false,
                        "Set to true if boundaries need to overlap on sideset to be detected.");
  params.addParam<MooseEnum>(
      "location", location, "Control of where the subdomain id is to be set");

  return params;
}

AddSideSetsFromBoundingBox::AddSideSetsFromBoundingBox(const InputParameters & parameters)
  : MeshModifier(parameters),
    _location(parameters.get<MooseEnum>("location")),
    _block_id(parameters.get<SubdomainID>("block_id")),
    _boundary_id_old(parameters.get<std::vector<BoundaryName>>("boundary_id_old")),
    _boundary_id_new(parameters.get<boundary_id_type>("boundary_id_new")),
    _bounding_box(parameters.get<RealVectorValue>("bottom_left"),
                  parameters.get<RealVectorValue>("top_right")),
    _boundary_id_overlap(parameters.get<bool>("boundary_id_overlap"))
{
}

void
AddSideSetsFromBoundingBox::modify()
{
  // this modifier is not designed for working with distributed mesh
  _mesh_ptr->errorIfDistributedMesh("BreakBoundaryOnSubdomain");

  // Check that we have access to the mesh
  if (!_mesh_ptr)
    mooseError("_mesh_ptr must be initialized before calling SubdomainBoundingBox::modify()");

  // Reference the the libMesh::MeshBase
  MeshBase & mesh = _mesh_ptr->getMesh();

  // Get a reference to our BoundaryInfo object for later use
  BoundaryInfo & boundary_info = mesh.get_boundary_info();

  bool found_element = false;
  bool found_side_sets = false;

  if (!_boundary_id_overlap)
  {
    // Loop over the elements
    for (const auto & elem : mesh.active_element_ptr_range())
    {
      // boolean if element centroid is in bounding box
      bool contains = _bounding_box.contains_point(elem->centroid());

      // check if active elements are found in the bounding box
      if (contains)
      {
        found_element = true;
        // loop over sides of elements within bounding box
        for (unsigned int side = 0; side < elem->n_sides(); side++)
          // loop over provided boundary vector to check all side sets for all boundary ids
          for (unsigned int boundary_id_number = 0; boundary_id_number < _boundary_id_old.size();
               boundary_id_number++)
            // check if side has same boundary id that you are looking for
            if (boundary_info.has_boundary_id(
                    elem, side, boundary_info.get_id_by_name(_boundary_id_old[boundary_id_number])))
            {
              // assign new boundary value to boundary which meets meshmodifier criteria
              boundary_info.add_side(elem, side, _boundary_id_new);
              found_side_sets = true;
            }
      }
    }
    if (!found_element)
      mooseError("No elements found within the bounding box");

    if (!found_side_sets)
      mooseError("No side sets found on active elements within the bounding box");
  }

  else if (_boundary_id_overlap)
  {
    if (_boundary_id_old.size() < 2)
      mooseError("boundary_id_old out of bounds: ",
                 _boundary_id_old.size(),
                 " Must be 2 boundary inputs or more.");

    bool found_node = false;
    const bool inside = (_location == "INSIDE");

    // Loop over the elements and assign node set id to nodes within the bounding box
    for (auto node = mesh.active_nodes_begin(); node != mesh.active_nodes_end(); ++node)
    {
      // check if nodes are inside of bounding box
      if (_bounding_box.contains_point(**node) == inside)
      {
        // read out boundary ids for nodes
        std::vector<short int> boundary_id_list = boundary_info.boundary_ids(*node);
        std::vector<boundary_id_type> boundary_id_old_list =
            _mesh_ptr->getBoundaryIDs(_boundary_id_old);

        // sort boundary ids on node and sort boundary ids provided in input file
        std::sort(boundary_id_list.begin(), boundary_id_list.end());
        std::sort(boundary_id_old_list.begin(), boundary_id_old_list.end());

        // check if input boundary ids are all contained in the node
        // if true, write new boundary id on respective node
        if (std::includes(boundary_id_list.begin(),
                          boundary_id_list.end(),
                          boundary_id_old_list.begin(),
                          boundary_id_old_list.end()))
        {
          boundary_info.add_node(*node, _boundary_id_new);
          found_node = true;
        }
      }
    }

    if (!found_node)
      mooseError("No nodes found within the bounding box");
  }
}
<commit_msg>Use boundary_id_type instead of 'short int'.<commit_after>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "AddSideSetsFromBoundingBox.h"
#include "Conversion.h"
#include "MooseMesh.h"
#include "MooseTypes.h"

registerMooseObject("MooseApp", AddSideSetsFromBoundingBox);

template <>
InputParameters
validParams<AddSideSetsFromBoundingBox>()
{
  InputParameters params = validParams<MeshModifier>();
  params.addClassDescription("Find sidesets with given boundary ids in bounding box and add new "
                             "boundary id. This can be done by finding all required boundary "
                             "and adding the new boundary id to those sidesets. Alternatively, "
                             "a number of boundary ids can be provided and all nodes within the "
                             "bounding box that have all the required boundary ids will have a new"
                             "boundary id added.");

  MooseEnum location("INSIDE OUTSIDE", "INSIDE");

  params.addRequiredParam<RealVectorValue>(
      "bottom_left", "The bottom left point (in x,y,z with spaces in-between).");
  params.addRequiredParam<RealVectorValue>(
      "top_right", "The bottom left point (in x,y,z with spaces in-between).");
  params.addRequiredParam<SubdomainID>("block_id",
                                       "Subdomain id to set for inside/outside the bounding box");
  params.addRequiredParam<std::vector<BoundaryName>>(
      "boundary_id_old", "Boundary id on specified block within the bounding box to select");
  params.addRequiredParam<boundary_id_type>(
      "boundary_id_new", "Boundary id on specified block within the bounding box to assign");
  params.addParam<bool>("boundary_id_overlap",
                        false,
                        "Set to true if boundaries need to overlap on sideset to be detected.");
  params.addParam<MooseEnum>(
      "location", location, "Control of where the subdomain id is to be set");

  return params;
}

AddSideSetsFromBoundingBox::AddSideSetsFromBoundingBox(const InputParameters & parameters)
  : MeshModifier(parameters),
    _location(parameters.get<MooseEnum>("location")),
    _block_id(parameters.get<SubdomainID>("block_id")),
    _boundary_id_old(parameters.get<std::vector<BoundaryName>>("boundary_id_old")),
    _boundary_id_new(parameters.get<boundary_id_type>("boundary_id_new")),
    _bounding_box(parameters.get<RealVectorValue>("bottom_left"),
                  parameters.get<RealVectorValue>("top_right")),
    _boundary_id_overlap(parameters.get<bool>("boundary_id_overlap"))
{
}

void
AddSideSetsFromBoundingBox::modify()
{
  // this modifier is not designed for working with distributed mesh
  _mesh_ptr->errorIfDistributedMesh("BreakBoundaryOnSubdomain");

  // Check that we have access to the mesh
  if (!_mesh_ptr)
    mooseError("_mesh_ptr must be initialized before calling SubdomainBoundingBox::modify()");

  // Reference the the libMesh::MeshBase
  MeshBase & mesh = _mesh_ptr->getMesh();

  // Get a reference to our BoundaryInfo object for later use
  BoundaryInfo & boundary_info = mesh.get_boundary_info();

  bool found_element = false;
  bool found_side_sets = false;

  if (!_boundary_id_overlap)
  {
    // Loop over the elements
    for (const auto & elem : mesh.active_element_ptr_range())
    {
      // boolean if element centroid is in bounding box
      bool contains = _bounding_box.contains_point(elem->centroid());

      // check if active elements are found in the bounding box
      if (contains)
      {
        found_element = true;
        // loop over sides of elements within bounding box
        for (unsigned int side = 0; side < elem->n_sides(); side++)
          // loop over provided boundary vector to check all side sets for all boundary ids
          for (unsigned int boundary_id_number = 0; boundary_id_number < _boundary_id_old.size();
               boundary_id_number++)
            // check if side has same boundary id that you are looking for
            if (boundary_info.has_boundary_id(
                    elem, side, boundary_info.get_id_by_name(_boundary_id_old[boundary_id_number])))
            {
              // assign new boundary value to boundary which meets meshmodifier criteria
              boundary_info.add_side(elem, side, _boundary_id_new);
              found_side_sets = true;
            }
      }
    }
    if (!found_element)
      mooseError("No elements found within the bounding box");

    if (!found_side_sets)
      mooseError("No side sets found on active elements within the bounding box");
  }

  else if (_boundary_id_overlap)
  {
    if (_boundary_id_old.size() < 2)
      mooseError("boundary_id_old out of bounds: ",
                 _boundary_id_old.size(),
                 " Must be 2 boundary inputs or more.");

    bool found_node = false;
    const bool inside = (_location == "INSIDE");

    // Loop over the elements and assign node set id to nodes within the bounding box
    for (auto node = mesh.active_nodes_begin(); node != mesh.active_nodes_end(); ++node)
    {
      // check if nodes are inside of bounding box
      if (_bounding_box.contains_point(**node) == inside)
      {
        // read out boundary ids for nodes
        std::vector<boundary_id_type> boundary_id_list = boundary_info.boundary_ids(*node);
        std::vector<boundary_id_type> boundary_id_old_list =
            _mesh_ptr->getBoundaryIDs(_boundary_id_old);

        // sort boundary ids on node and sort boundary ids provided in input file
        std::sort(boundary_id_list.begin(), boundary_id_list.end());
        std::sort(boundary_id_old_list.begin(), boundary_id_old_list.end());

        // check if input boundary ids are all contained in the node
        // if true, write new boundary id on respective node
        if (std::includes(boundary_id_list.begin(),
                          boundary_id_list.end(),
                          boundary_id_old_list.begin(),
                          boundary_id_old_list.end()))
        {
          boundary_info.add_node(*node, _boundary_id_new);
          found_node = true;
        }
      }
    }

    if (!found_node)
      mooseError("No nodes found within the bounding box");
  }
}
<|endoftext|>