text:
#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>
#include <mitama/result/result.hpp>
#include <mitama/result/result_io.hpp>
#include <mitama/maybe/maybe.hpp>
#include <mitama/maybe/range_to_maybe.hpp>

#include <boost/xpressive/xpressive.hpp>

#include <string>

using namespace mitama;
using namespace std::string_literals;

TEST_CASE("is_just()", "[maybe][is_just]"){
  maybe<int> x = just(2);
  REQUIRE( x.is_just() );

  maybe<int> y = nothing;
  REQUIRE_FALSE( y.is_just() );
}

TEST_CASE("is_nothing()", "[maybe][is_nothing]"){
  maybe<int> x = just(2);
  REQUIRE_FALSE( x.is_nothing() );

  maybe<int> y = nothing;
  REQUIRE( y.is_nothing() );
}

TEST_CASE("unwrap()", "[maybe][unwrap]"){
  {
    maybe x = just("air"s);
    REQUIRE(x.unwrap() == "air"s);
  }
  try {
    maybe<int> x = nothing;
    x.unwrap(); // panics
  }
  catch (runtime_panic const &p)
  {
    using namespace boost::xpressive;
    sregex re =
        as_xpr(
            "runtime panicked at 'called `maybe::unwrap()` on a `nothing` value', ") >>
        *_ >> as_xpr(":") >> +range('0', '9');
    smatch what;
    REQUIRE(regex_match(std::string{p.what()}, what, re));
  }
}

TEST_CASE("expect()", "[maybe][expect]"){
  {
    maybe x = just("air"s);
    REQUIRE(x.expect("the world is ending") == "air"s);
  }
  try {
    maybe<int> x = nothing;
    x.expect("the world is ending"); // panics
  }
  catch (runtime_panic const &p)
  {
    using namespace boost::xpressive;
    sregex re =
        as_xpr(
            "runtime panicked at 'the world is ending', ") >>
        *_ >> as_xpr(":") >> +range('0', '9');
    smatch what;
    REQUIRE(regex_match(std::string{p.what()}, what, re));
  }
}

TEST_CASE("cloned()", "[maybe][cloned]"){
  int x = 12;
  maybe<int&> opt_x = just(x);
  REQUIRE(opt_x == just(12));
  REQUIRE(&(opt_x.unwrap()) == &x);

  auto shallow_copied = opt_x;
  REQUIRE(&(shallow_copied.unwrap()) == &x);

  auto cloned = opt_x.cloned();
  REQUIRE(cloned == just(12));
  REQUIRE(&(cloned.unwrap()) != &x);
}

TEST_CASE("unwrap_or()", "[maybe][unwrap_or]"){
  REQUIRE(maybe{just("car"s)}.unwrap_or("bike"s) == "car"s);
  REQUIRE(maybe<std::string>{nothing}.unwrap_or("bike"s) == "bike"s);
}

TEST_CASE("unwrap_or_else()", "[maybe][unwrap_or_else]"){
  int k = 10;
  REQUIRE(maybe{just(4)}.unwrap_or_else([k]{ return 2 * k; }) == 4);
  REQUIRE(maybe<int>{}.unwrap_or_else([k]{ return 2 * k; }) == 20);
}

TEST_CASE("map()", "[maybe][map]"){

  maybe maybe_some_string = just("Hello, World!"s);
  // `maybe::map` takes self *by ref*,
  // *not* consuming `maybe_some_string`
  maybe maybe_some_len = maybe_some_string.map(&std::string::size);

  REQUIRE(maybe_some_len == just(13u));

  maybe some_list = just(std::vector<int>{1,2,3,4,5});
  auto acc = [](auto&& range, auto init) -> double { return std::accumulate(range.begin(), range.end(), init); };
  maybe sum = some_list.map(acc, 0.0);

  REQUIRE(sum == just(15));
}

TEST_CASE("map_or()", "[maybe][map_or]"){

  maybe x = just("foo"s);
  REQUIRE(x.map_or(42, &std::string::size) == 3);

  maybe<std::string> y = nothing;
  REQUIRE(y.map_or(42, &std::string::size) == 42);

  maybe some_num = just(1);

  maybe z = some_num.map_or(0, std::plus{}, 1);

  REQUIRE(z == just(2));
}

TEST_CASE("map_or_else()", "[maybe][map_or_else]"){
  int k = 21;

  maybe x = just("foo"s);
  REQUIRE(x.map_or_else([k]{ return 2 * k; }, &std::string::size) == 3);

  maybe<std::string> y = nothing;
  REQUIRE(y.map_or_else([k]{ return 2 * k; }, &std::string::size) == 42);
  REQUIRE(x.map_or_else([]{ return "default"s; }, std::plus{}, "bar"s) == "foobar"s);
  REQUIRE(y.map_or_else([]{ return "default"s; }, std::plus{}, "bar"s) == "default"s);

  maybe z = just(1);
  REQUIRE(z.map_or_else([k]{ return 2 * k; }, std::plus{}, 1) == 2);
}

TEST_CASE("ok_or()", "[maybe][ok_or]"){

  maybe x = just("foo"s);
  REQUIRE(x.ok_or(0) == success("foo"s));

  maybe<std::string> y = nothing;
  REQUIRE(y.ok_or(0) == failure(0));

  REQUIRE(y.ok_or() == failure<>());

}

TEST_CASE("ok_or_else()", "[maybe][ok_or_else]"){

  maybe x = just("foo"s);
  REQUIRE(x.ok_or_else([]{ return 0; }) == success("foo"s));

  maybe<std::string> y = nothing;
  REQUIRE(y.ok_or_else([]{ return 0; }) == failure(0));

}

TEST_CASE("conj()", "[maybe][conj]"){
{
  maybe x = just(2);
  maybe<std::string> y = nothing;
  REQUIRE(x.conj(y) == nothing);
  REQUIRE((x&&y) == nothing);
}
{
  maybe<int> x = nothing;
  maybe y = just("foo"s);
  REQUIRE(x.conj(y) == nothing);
  REQUIRE((x&&y) == nothing);
}
{
  maybe x = just(2);
  maybe y = just("foo"s);
  REQUIRE(x.conj(y) == just("foo"s));
  REQUIRE((x&&y) == just("foo"s));
}
{
  maybe<int> x = nothing;
  maybe<std::string> y = nothing;
  REQUIRE(x.conj(y) == nothing);
  REQUIRE((x&&y) == nothing);
}
}

TEST_CASE("and_then()", "[maybe][and_then]"){

  auto sq = [](int x) -> maybe<int> { return just(x * x); };
  auto nope = [](...) -> maybe<int> { return nothing; };
  auto is_eq = [](int a, int b) { return a == b ? maybe<int>{a} : nothing; };

  REQUIRE(maybe{just(2)}.and_then(sq).and_then(sq) == just(16));
  REQUIRE(maybe{just(2)}.and_then(sq).and_then(nope) == nothing);
  REQUIRE(maybe{just(2)}.and_then(nope).and_then(sq) == nothing);
  REQUIRE(maybe{just(2)}.and_then(is_eq, 2) == just(2));
  REQUIRE(nope().and_then(sq).and_then(sq) == nothing);
}

TEST_CASE("filter()", "[maybe][filter]"){

  auto is_even = [](int n) -> bool {
    return n % 2 == 0;
  };

  REQUIRE(maybe<int>{}.filter(is_even) == nothing);
  REQUIRE(maybe{just(3)}.filter(is_even) == nothing);
  REQUIRE(maybe{just(4)}.filter(is_even) == just(4));

}

TEST_CASE("disj()", "[maybe][disj]"){
{
  maybe x = just(2);
  maybe<int> y = nothing;
  assert(x.disj(y) == just(2));
  assert((x||y) == just(2));
}
{
  maybe<int> x = nothing;
  maybe y = just(100);
  assert(x.disj(y) == just(100));
  assert((x||y) == just(100));
}
{
  maybe x = just(2);
  maybe y = just(100);
  assert(x.disj(y) == just(2));
  assert((x||y) == just(2));
}
{
  maybe<int> x = nothing;
  maybe<int> y = nothing;
  assert(x.disj(y) == nothing);
  assert((x||y) == nothing);
}
}

TEST_CASE("or_else()", "[maybe][or_else]"){

  auto nobody = []() -> maybe<std::string> { return nothing; };
  auto vikings = []() -> maybe<std::string> { return just("vikings"s); };
  auto to_maybe = [](auto&& e) -> maybe<std::decay_t<decltype(e)>> { return just(std::forward<decltype(e)>(e)); };

  REQUIRE(maybe{just("barbarians"s)}.or_else(vikings) == just("barbarians"s));
  REQUIRE(maybe<std::string>{}.or_else(vikings) == just("vikings"s));
  REQUIRE(maybe<std::string>{}.or_else(to_maybe, "vikings"s) == just("vikings"s));
  REQUIRE(maybe<std::string>{}.or_else(nobody) == nothing);

}

TEST_CASE("xdisj()", "[maybe][xdisj]"){
{
  maybe x = just(2);
  maybe<int> y = nothing;
  assert(x.xdisj(y) == just(2));
  assert((x^y) == just(2));
}
{
  maybe<int> x = nothing;
  maybe y = just(100);
  assert(x.xdisj(y) == just(100));
  assert((x^y) == just(100));
}
{
  maybe x = just(2);
  maybe y = just(100);
  assert(x.xdisj(y) == nothing);
  assert((x^y) == nothing);
}
{
  maybe<int> x = nothing;
  maybe<int> y = nothing;
  assert(x.xdisj(y) == nothing);
  assert((x^y) == nothing);
}
}

struct noncopyable {
  noncopyable() = default;
  noncopyable(noncopyable const&) = delete;
  noncopyable& operator=(noncopyable const&) = delete;
  noncopyable(noncopyable&&) = default;
  noncopyable& operator=(noncopyable&&) = default;

  bool operator==(noncopyable&&) & {
    return true;
  }
  bool operator==(noncopyable&&) const& {
    return true;
  }
  bool operator==(noncopyable const&) & {
    return true;
  }
  bool operator==(noncopyable const&) const& {
    return true;
  }

  friend std::ostream& operator<<(std::ostream& os, noncopyable&) {
    return os << "noncopyable&";
  }
  friend std::ostream& operator<<(std::ostream& os, noncopyable const&) {
    return os << "noncopyable const&";
  }
  friend std::ostream& operator<<(std::ostream& os, noncopyable&&) {
    return os << "noncopyable&&";
  }
};

TEST_CASE("get_or_emplace()", "[maybe][get_or_emplace]"){
    maybe<noncopyable> x = nothing;
    auto& y = x.get_or_emplace(noncopyable{});
    REQUIRE(y == noncopyable{});
}

TEST_CASE("get_or_emplace_with()", "[maybe][get_or_emplace_with]"){
  GIVEN("a nothing type of maybe<int>.") {
    maybe<int> x = nothing;
    WHEN("call get_or_emplace_with and bind to `y`."){
      std::ignore = x.get_or_emplace_with([]{ return 5; });
      std::ignore = x.get_or_emplace_with([](auto x){ return x; }, 5);
      auto& y = x.get_or_emplace_with(&std::string::size , "12345"s);
      REQUIRE(y == 5);
      WHEN("assign 7 to `y`") {
        y = 7;
        THEN("changed x to just(7)"){
          REQUIRE(x == just(7));
        }
      }
    }
  }
}

TEST_CASE("as_ref()", "[maybe][as_ref]"){
  {
    maybe x = just(5);
    auto ref = x.as_ref();
    REQUIRE(x == just(5));
    ref.unwrap() = 2;
    REQUIRE(x == just(2));
  }
}

TEST_CASE("replace()", "[maybe][replace]"){
  {
    maybe x = just(2);
    auto old = x.replace(5);
    REQUIRE(x == just(5));
    REQUIRE(old == just(2));
  }
  {
    maybe<int> x = nothing;
    auto old = x.replace(3);
    REQUIRE(x == just(3));
    REQUIRE(old == nothing);
  }
}

TEST_CASE("transpose()", "[maybe][transpose]"){

  result<maybe<int>, std::string> x = success(just(5));
  maybe<result<int, std::string>> y = just(success(5));
  REQUIRE(x == y.transpose());

}

TEST_CASE("unwrap_or_default()", "[maybe][unwrap_or_default]"){

  maybe<std::string> x = nothing;
  REQUIRE(x.unwrap_or_default() == ""s);

}

TEST_CASE("flatten()", "[maybe][flatten]"){

  maybe<maybe<int>> x = just(just(6));
  REQUIRE(just(6) == x.flatten());

  maybe<maybe<int>> y = just(nothing);
  REQUIRE(nothing == y.flatten());

  maybe<maybe<int>> z = nothing;
  REQUIRE(nothing == z.flatten());

  // Flattening once only removes one level of nesting:
  maybe<maybe<maybe<int>>> nest = just(just(just(6)));
  REQUIRE(just(6) == nest.flatten().flatten());

}

TEST_CASE("and_finally()", "[maybe][and_finally]"){

  std::string hook = "default";
  maybe<std::string> x = nothing;
  x.and_finally([&hook](std::string v){
    hook = v;
  });
  REQUIRE(hook == "default"s);

  maybe y = just("error"s);
  y.and_finally([&hook](std::string v){
    hook = v;
  });
  REQUIRE(hook == "error"s);

}

TEST_CASE("or_finally()", "[maybe][or_finally]"){

  std::string hook = "default";
  maybe<int> x = nothing;
  x.or_finally([&hook]{
    hook = "error";
  });
  REQUIRE(hook == "error"s);

}

TEST_CASE("and_peek() test", "[maybe][and_peek]"){
  maybe x = just(42);
  REQUIRE(x.and_peek([](int& v){ v = 57; }) == just(57));
  int y = 0;
  REQUIRE((std::as_const(x).and_peek([&y](auto&& v){ y = v; }), y) == x.unwrap());
}

TEST_CASE("or_peek() test", "[maybe][and_peek]"){
  maybe<int> x = nothing;
  int hook = 0;
  REQUIRE(x.or_peek([&hook]{ hook = 57; }) == nothing);
  REQUIRE(hook == 57);
}

struct base {
  virtual ~base() = default;
  virtual std::string test() { return "base"; }
};

struct derived final: base {
  virtual std::string test() override { return "derived"; }
};

TEST_CASE("reference of abstract", "[maybe][abstract]"){
  derived _derived = {};
  maybe<base&> x = just(_derived);
  REQUIRE(x->test() == "derived"s);
  base _base = {};
  x = just(_base);
  REQUIRE(x->test() == "base"s);
}

TEST_CASE("equal", "[maybe][equal]"){
  maybe<int> just1 = just(1);
  maybe<int> just2 = just(2);
  maybe<int> none = nothing;

  REQUIRE_FALSE(just1 == just2);
  REQUIRE_FALSE(just2 == just1);
  REQUIRE(just1 == just1);
  REQUIRE(just2 == just2);

  REQUIRE_FALSE(just1 == 2);
  REQUIRE_FALSE(just2 == 1);
  REQUIRE(just1 == 1);
  REQUIRE(just2 == 2);

  REQUIRE_FALSE(1 == just2);
  REQUIRE_FALSE(2 == just1);
  REQUIRE(1 == just1);
  REQUIRE(2 == just2);

  REQUIRE_FALSE(just(1) == just2);
  REQUIRE_FALSE(just(2) == just1);
  REQUIRE(just(1) == just1);
  REQUIRE(just(2) == just2);

  REQUIRE_FALSE(just1 == just(2));
  REQUIRE_FALSE(just2 == just(1));
  REQUIRE(just1 == just(1));
  REQUIRE(just2 == just(2));

  REQUIRE_FALSE(just(1) == just(2));
  REQUIRE_FALSE(just(2) == just(1));
  REQUIRE(just(1) == just(1));
  REQUIRE(just(2) == just(2));

  REQUIRE(none == none);
  REQUIRE(nothing == none);
  REQUIRE(none == nothing);
  REQUIRE(nothing == nothing);

  REQUIRE_FALSE(none == just1);
  REQUIRE_FALSE(none == just2);
  REQUIRE_FALSE(none == 1);
  REQUIRE_FALSE(none == 2);

  REQUIRE_FALSE(1 == none);
  REQUIRE_FALSE(2 == none);

  REQUIRE_FALSE(just1 == none);
  REQUIRE_FALSE(just2 == none);

  REQUIRE_FALSE(nothing == just1);
  REQUIRE_FALSE(nothing == just2);

  REQUIRE_FALSE(none == just(1));
  REQUIRE_FALSE(none == just(2));

  REQUIRE_FALSE(nothing == just(1));
  REQUIRE_FALSE(nothing == just(2));

  REQUIRE_FALSE(just1 == none);
  REQUIRE_FALSE(just2 == none);

  REQUIRE_FALSE(just(1) == none);
  REQUIRE_FALSE(just(2) == none);

  REQUIRE_FALSE(just1 == nothing);
  REQUIRE_FALSE(just2 == nothing);

  REQUIRE_FALSE(just(1) == nothing);
  REQUIRE_FALSE(just(2) == nothing);
}

TEST_CASE("not_equal", "[maybe][not_equal]"){
  maybe<int> just1 = just(1);
  maybe<int> just2 = just(2);
  maybe<int> none = nothing;

  REQUIRE(just1 != just2);
  REQUIRE(just2 != just1);
  REQUIRE_FALSE(just1 != just1);
  REQUIRE_FALSE(just2 != just2);

  REQUIRE(just1 != 2);
  REQUIRE(just2 != 1);
  REQUIRE_FALSE(just1 != 1);
  REQUIRE_FALSE(just2 != 2);

  REQUIRE(1 != just2);
  REQUIRE(2 != just1);
  REQUIRE_FALSE(1 != just1);
  REQUIRE_FALSE(2 != just2);

  REQUIRE(just(1) != just2);
  REQUIRE(just(2) != just1);
  REQUIRE_FALSE(just(1) != just1);
  REQUIRE_FALSE(just(2) != just2);

  REQUIRE(just1 != just(2));
  REQUIRE(just2 != just(1));
  REQUIRE_FALSE(just1 != just(1));
  REQUIRE_FALSE(just2 != just(2));

  REQUIRE(just(1) != just(2));
  REQUIRE(just(2) != just(1));
  REQUIRE_FALSE(just(1) != just(1));
  REQUIRE_FALSE(just(2) != just(2));

  REQUIRE_FALSE(none != none);
  REQUIRE_FALSE(nothing != none);
  REQUIRE_FALSE(none != nothing);
  REQUIRE_FALSE(nothing != nothing);

  REQUIRE(none != just1);
  REQUIRE(none != just2);
  REQUIRE(none != 1);
  REQUIRE(none != 2);

  REQUIRE(1 != none);
  REQUIRE(2 != none);

  REQUIRE(just1 != none);
  REQUIRE(just2 != none);

  REQUIRE(nothing != just1);
  REQUIRE(nothing != just2);

  REQUIRE(none != just(1));
  REQUIRE(none != just(2));

  REQUIRE(nothing != just(1));
  REQUIRE(nothing != just(2));

  REQUIRE(just1 != none);
  REQUIRE(just2 != none);

  REQUIRE(just(1) != none);
  REQUIRE(just(2) != none);

  REQUIRE(just1 != nothing);
  REQUIRE(just2 != nothing);

  REQUIRE(just(1) != nothing);
  REQUIRE(just(2) != nothing);
}

TEST_CASE("less compare", "[maybe][less]"){
  maybe<int> just1 = just(1);
  maybe<int> just2 = just(2);
  maybe<int> none = nothing;

  REQUIRE(just1 < just2);
  REQUIRE_FALSE(just2 < just1);
  REQUIRE_FALSE(just1 < just1);
  REQUIRE_FALSE(just2 < just2);

  REQUIRE(just1 < 2);
  REQUIRE_FALSE(just2 < 1);
  REQUIRE_FALSE(just1 < 1);
  REQUIRE_FALSE(just2 < 2);

  REQUIRE(1 < just2);
  REQUIRE_FALSE(2 < just1);
  REQUIRE_FALSE(1 < just1);
  REQUIRE_FALSE(2 < just2);

  REQUIRE(just(1) < just2);
  REQUIRE_FALSE(just(2) < just1);
  REQUIRE_FALSE(just(1) < just1);
  REQUIRE_FALSE(just(2) < just2);

  REQUIRE(just1 < just(2));
  REQUIRE_FALSE(just2 < just(1));
  REQUIRE_FALSE(just1 < just(1));
  REQUIRE_FALSE(just2 < just(2));

  REQUIRE(just(1) < just(2));
  REQUIRE_FALSE(just(2) < just(1));
  REQUIRE_FALSE(just(1) < just(1));
  REQUIRE_FALSE(just(2) < just(2));

  REQUIRE_FALSE(none < none);
  REQUIRE_FALSE(nothing < none);
  REQUIRE_FALSE(none < nothing);
  REQUIRE_FALSE(nothing < nothing);

  REQUIRE(none < just1);
  REQUIRE(none < just2);
  REQUIRE(none < 1);
  REQUIRE(none < 2);

  REQUIRE_FALSE(1 < none);
  REQUIRE_FALSE(2 < none);

  REQUIRE_FALSE(just1 < none);
  REQUIRE_FALSE(just2 < none);

  REQUIRE(nothing < just1);
  REQUIRE(nothing < just2);

  REQUIRE(none < just(1));
  REQUIRE(none < just(2));

  REQUIRE(nothing < just(1));
  REQUIRE(nothing < just(2));

  REQUIRE_FALSE(just1 < none);
  REQUIRE_FALSE(just2 < none);

  REQUIRE_FALSE(just(1) < none);
  REQUIRE_FALSE(just(2) < none);

  REQUIRE_FALSE(just1 < nothing);
  REQUIRE_FALSE(just2 < nothing);

  REQUIRE_FALSE(just(1) < nothing);
  REQUIRE_FALSE(just(2) < nothing);

}

TEST_CASE("less_or_equal compare", "[maybe][less_or_equal]"){
  maybe<int> just1 = just(1);
  maybe<int> just2 = just(2);
  maybe<int> none = nothing;

  REQUIRE(just1 <= just2);
  REQUIRE_FALSE(just2 <= just1);
  REQUIRE(just1 <= just1);
  REQUIRE(just2 <= just2);

  REQUIRE(just1 <= 2);
  REQUIRE_FALSE(just2 <= 1);
  REQUIRE(just1 <= 1);
  REQUIRE(just2 <= 2);

  REQUIRE(1 <= just2);
  REQUIRE_FALSE(2 <= just1);
  REQUIRE(1 <= just1);
  REQUIRE(2 <= just2);

  REQUIRE(just(1) <= just2);
  REQUIRE_FALSE(just(2) <= just1);
  REQUIRE(just(1) <= just1);
  REQUIRE(just(2) <= just2);

  REQUIRE(just1 <= just(2));
  REQUIRE_FALSE(just2 <= just(1));
  REQUIRE(just1 <= just(1));
  REQUIRE(just2 <= just(2));

  REQUIRE(just(1) <= just(2));
  REQUIRE_FALSE(just(2) <= just(1));
  REQUIRE(just(1) <= just(1));
  REQUIRE(just(2) <= just(2));

  REQUIRE(none <= none);
  REQUIRE(nothing <= none);
  REQUIRE(none <= nothing);
  REQUIRE(nothing <= nothing);

  REQUIRE(none <= just1);
  REQUIRE(none <= just2);

  REQUIRE(none <= 1);
  REQUIRE(none <= 2);

  REQUIRE(nothing <= just1);
  REQUIRE(nothing <= just2);

  REQUIRE(none <= just(1));
  REQUIRE(none <= just(2));

  REQUIRE(nothing <= just(1));
  REQUIRE(nothing <= just(2));

  REQUIRE_FALSE(just1 <= none);
  REQUIRE_FALSE(just2 <= none);

  REQUIRE_FALSE(1 <= none);
  REQUIRE_FALSE(2 <= none);

  REQUIRE_FALSE(just(1) <= none);
  REQUIRE_FALSE(just(2) <= none);

  REQUIRE_FALSE(just1 <= nothing);
  REQUIRE_FALSE(just2 <= nothing);

  REQUIRE_FALSE(just(1) <= nothing);
  REQUIRE_FALSE(just(2) <= nothing);

}

TEST_CASE("greater compare", "[maybe][greater]"){
  maybe<int> just1 = just(1);
  maybe<int> just2 = just(2);
  maybe<int> none = nothing;

  REQUIRE_FALSE(just1 > just2);
  REQUIRE(just2 > just1);
  REQUIRE_FALSE(just1 > just1);
  REQUIRE_FALSE(just2 > just2);

  REQUIRE_FALSE(just1 > 2);
  REQUIRE(just2 > 1);
  REQUIRE_FALSE(just1 > 1);
  REQUIRE_FALSE(just2 > 2);

  REQUIRE_FALSE(1 > just2);
  REQUIRE(2 > just1);
  REQUIRE_FALSE(1 > just1);
  REQUIRE_FALSE(2 > just2);

  REQUIRE_FALSE(just(1) > just2);
  REQUIRE(just(2) > just1);
  REQUIRE_FALSE(just(1) > just1);
  REQUIRE_FALSE(just(2) > just2);

  REQUIRE_FALSE(just1 > just(2));
  REQUIRE(just2 > just(1));
  REQUIRE_FALSE(just1 > just(1));
  REQUIRE_FALSE(just2 > just(2));

  REQUIRE_FALSE(just(1) > just(2));
  REQUIRE(just(2) > just(1));
  REQUIRE_FALSE(just(1) > just(1));
  REQUIRE_FALSE(just(2) > just(2));

  REQUIRE_FALSE(none > none);
  REQUIRE_FALSE(nothing > none);
  REQUIRE_FALSE(none > nothing);
  REQUIRE_FALSE(nothing > nothing);

  REQUIRE_FALSE(none > just1);
  REQUIRE_FALSE(none > just2);

  REQUIRE_FALSE(none > 1);
  REQUIRE_FALSE(none > 2);

  REQUIRE_FALSE(nothing > just1);
  REQUIRE_FALSE(nothing > just2);

  REQUIRE_FALSE(none > just(1));
  REQUIRE_FALSE(none > just(2));

  REQUIRE_FALSE(nothing > just(1));
  REQUIRE_FALSE(nothing > just(2));

  REQUIRE(just1 > none);
  REQUIRE(just2 > none);

  REQUIRE(1 > none);
  REQUIRE(2 > none);

  REQUIRE(just(1) > none);
  REQUIRE(just(2) > none);

  REQUIRE(just1 > nothing);
  REQUIRE(just2 > nothing);

  REQUIRE(just(1) > nothing);
  REQUIRE(just(2) > nothing);

}

TEST_CASE("greater_or_equal compare", "[maybe][greater_or_equal]"){
  maybe<int> just1 = just(1);
  maybe<int> just2 = just(2);
  maybe<int> none = nothing;

  REQUIRE_FALSE(just1 >= just2);
  REQUIRE(just2 >= just1);
  REQUIRE(just1 >= just1);
  REQUIRE(just2 >= just2);

  REQUIRE_FALSE(just1 >= 2);
  REQUIRE(just2 >= 1);
  REQUIRE(just1 >= 1);
  REQUIRE(just2 >= 2);

  REQUIRE_FALSE(1 >= just2);
  REQUIRE(2 >= just1);
  REQUIRE(1 >= just1);
  REQUIRE(2 >= just2);

  REQUIRE_FALSE(just(1) >= just2);
  REQUIRE(just(2) >= just1);
  REQUIRE(just(1) >= just1);
  REQUIRE(just(2) >= just2);

  REQUIRE_FALSE(just1 >= just(2));
  REQUIRE(just2 >= just(1));
  REQUIRE(just1 >= just(1));
  REQUIRE(just2 >= just(2));

  REQUIRE_FALSE(just(1) >= just(2));
  REQUIRE(just(2) >= just(1));
  REQUIRE(just(1) >= just(1));
  REQUIRE(just(2) >= just(2));

  REQUIRE(none >= none);
  REQUIRE(nothing >= none);
  REQUIRE(none >= nothing);
  REQUIRE(nothing >= nothing);

  REQUIRE_FALSE(nothing >= just1);
  REQUIRE_FALSE(nothing >= just2);

  REQUIRE_FALSE(none >= just1);
  REQUIRE_FALSE(none >= just2);

  REQUIRE_FALSE(none >= 1);
  REQUIRE_FALSE(none >= 2);

  REQUIRE_FALSE(none >= just(1));
  REQUIRE_FALSE(none >= just(2));

  REQUIRE_FALSE(nothing >= just(1));
  REQUIRE_FALSE(nothing >= just(2));

  REQUIRE(just1 >= none);
  REQUIRE(just2 >= none);

  REQUIRE(1 >= none);
  REQUIRE(2 >= none);

  REQUIRE(just(1) >= none);
  REQUIRE(just(2) >= none);

  REQUIRE(just1 >= nothing);
  REQUIRE(just2 >= nothing);

  REQUIRE(just(1) >= nothing);
  REQUIRE(just(2) >= nothing);

}

TEST_CASE("format test", "[maybe][format]"){
  using str = std::string;
  SECTION("just"){
    using namespace std::literals;
    std::stringstream ss;
    ss << just(1);
    REQUIRE(ss.str() ==  "just(1)"s);
  }
  SECTION("maybe of just"){
    using namespace std::literals;
    std::stringstream ss;
    ss << maybe<int>{just(1)};
    REQUIRE(ss.str() ==  "just(1)"s);
  }
  SECTION("just of range"){
    using namespace std::literals;
    std::stringstream ss;
    ss << just(std::vector<std::string>{"foo"s, "bar"s});
    REQUIRE(ss.str() == "just([\"foo\",\"bar\"])"s);
  }
  SECTION("result of range err"){
    using namespace std::literals;
    std::stringstream ss;
    ss << maybe(just(std::vector<std::string>{"foo"s, "bar"s}));
    REQUIRE(ss.str() == "just([\"foo\",\"bar\"])"s);
  }
  SECTION("just of tuple"){
    using namespace std::literals;
    std::stringstream ss;
    ss << just(std::tuple{"foo"s, 1});
    REQUIRE(ss.str() == "just((\"foo\",1))"s);
  }
  SECTION("maybe of just tuple"){
    using namespace std::literals;
    std::stringstream ss;
    ss << maybe(just(std::tuple{"foo"s, 1}));
    REQUIRE(ss.str() == "just((\"foo\",1))"s);
  }
  SECTION("just of dictionary"){
    using namespace std::literals;
    {
      std::stringstream ss;
      ss << just(std::map<str, int>{{"foo"s, 1}});
      REQUIRE(ss.str() == "just({\"foo\": 1})"s);
    }
  }
  SECTION("maybe of just dictionary"){
    using namespace std::literals;
    {
      std::stringstream ss;
      ss << maybe<std::map<str, int>>(just(std::map<str, int>{{"foo"s, 1}}));
      REQUIRE(ss.str() == "just({\"foo\": 1})"s);
    }
  }
  SECTION("just of tuple of tuple"){
    using namespace std::literals;
    {
      std::stringstream ss;
      ss << just(std::tuple{std::tuple{1, 1}, 1});
      REQUIRE(ss.str() == "just(((1,1),1))"s);
    }
  }
  SECTION("maybe of just tuple of tuple"){
    using namespace std::literals;
    {
      std::stringstream ss;
      ss << maybe(just(std::tuple{std::tuple{1, 1}, 1}));
      REQUIRE(ss.str() == "just(((1,1),1))"s);
    }
  }
}

TEST_CASE("forward mode test", "[maybe][forward]"){
  maybe<std::string> aaaaaaaaaa = just(10, 'a');
  REQUIRE(aaaaaaaaaa == just("aaaaaaaaaa"));

  maybe<std::vector<int>> vec = just({1,2,3});
  REQUIRE(vec == just(std::vector{1,2,3}));
}

TEST_CASE("range_to_maybe test", "[maybe][range_to_maybe]"){
  std::vector v{1,2,3};
  maybe x = range_to_maybe(v);
  REQUIRE(x == just(1));

  maybe y = range_to_maybe(std::vector<int>{});
  REQUIRE(y == nothing);

  int a[] = {1};
  maybe z = range_to_maybe(a);
  REQUIRE(z == 1);
}

#include <mitama/boolinators.hpp>

TEST_CASE("as_maybe test", "[maybe][as_maybe][boolinators]"){
  maybe x = as_maybe(true);
  REQUIRE(x == just(std::monostate{}));
  maybe y = as_maybe(false);
  REQUIRE(y == nothing);
}

TEST_CASE("as_just test", "[maybe][as_just][boolinators]"){
  maybe x = as_just(true, 1);
  REQUIRE(x == just(1));
  maybe y = as_just(false, 1);
  REQUIRE(y == nothing);
}

TEST_CASE("as_just_from test", "[maybe][as_just_from][boolinators]"){
  maybe x = as_just_from(true, []{ return 1; });
  REQUIRE(x == just(1));
  maybe y = as_just_from(false, []{ return 1; });
  REQUIRE(y == nothing);
}

max_stars_repo_name: ken-matsui/mitama-cpp-result

max_issues_repo_name: ken-matsui/mitama-cpp-result

max_forks_repo_name: ken-matsui/mitama-cpp-result


text:
/*
 * MutexConstraint.cpp
 * @brief Mutually exclusive constraint
 * @date Mar 20, 2022
 * @author Yoonwoo Kim
 */

#include <gtsam/base/Testable.h>
#include <gtsam/discrete/DecisionTreeFactor.h>
#include <cpp/planning/MutexConstraint.h>
#include <cpp/planning/NotSingleValueConstraint.h>
#include <cpp/planning/SingleValueConstraint.h>
#include <cpp/planning/OrConstraint.h>

#include <boost/make_shared.hpp>
using namespace gtsam;
using namespace std;

namespace gtsam_planner {

/* ************************************************************************* */
MutexConstraint::MutexConstraint(const DiscreteKeys& dkeys,
  const vector<size_t>& values) : DiscreteFactor(dkeys.indices()) {
  for (const DiscreteKey& dkey : dkeys) cardinalities_.insert(dkey);
  for (const size_t& value : values) values_.push_back(value);
}

/* ************************************************************************* */
void MutexConstraint::print(const std::string& s, const KeyFormatter& formatter) const {
  std::cout << s << "MutexConstraint on ";
  for (Key dkey : keys_) std::cout << formatter(dkey) << " ";
  std::cout << std::endl;
}

/* ************************************************************************* */
double MutexConstraint::operator()(const DiscreteValues& values) const {
  size_t count = 0;
  for (size_t i=0; i < values_.size(); i++) {
    size_t value = values.at(keys_[i]);
    if (value == values_[i]) count++;
    if (count > 1.0) return 0.0;
  }
  return 1.0;
}

/* ************************************************************************* */
DecisionTreeFactor MutexConstraint::toDecisionTreeFactor() const {
  vector<DecisionTreeFactor> factors;
  size_t nrKeys = keys_.size();
  for (size_t i = 0; i < nrKeys; i++) {
    SingleValueConstraint single(discreteKey(i), values_[i]);
    DecisionTreeFactor singleTree = single.toDecisionTreeFactor();
    for (size_t j = 0; j < nrKeys; j++) {
      if (i == j) continue;
      NotSingleValueConstraint notSingle(discreteKey(j), values_[j]);
      singleTree = singleTree * notSingle.toDecisionTreeFactor();
    }
    factors.push_back(singleTree);
  }
  OrConstraint mutex(factors);
  DecisionTreeFactor mutex_tree = mutex.toDecisionTreeFactor();
  return mutex_tree;
}

/* ************************************************************************* */
DecisionTreeFactor MutexConstraint::operator*(const DecisionTreeFactor& f) const {
  // TODO: can we do this more efficiently?
  return toDecisionTreeFactor() * f;
}

/* ************************************************************************* */
}  // namespace gtsam

ext: cpp


text: #include <boost/container/pmr/slist.hpp>

ext: hpp

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
#pragma once
#include <cmath>
#include <autoppl/math/math.hpp>
#include <autoppl/util/traits/dist_expr_traits.hpp>
#include <fastad_bits/util/type_traits.hpp>
#include <Eigen/Dense>

// MSVC does not seem to support M_PI
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

namespace ppl {
namespace math {

using dist_value_t = util::dist_value_t;

/////////////////////////////////
// Compile-time Constants
/////////////////////////////////

inline constexpr double SQRT_TWO_PI =
    2.506628274631000502415765284811045;
inline constexpr double LOG_SQRT_TWO_PI =
    0.918938533204672741780329736405617;

/////////////////////////////////
// Normal Density
/////////////////////////////////

// sss
template <class XType
        , class MeanType
        , class SigmaType
        , class = std::enable_if_t<
            std::is_arithmetic_v<XType> &&
            std::is_arithmetic_v<MeanType> &&
            std::is_arithmetic_v<SigmaType>
        > >
inline dist_value_t normal_pdf(const XType& x,
                               const MeanType& mean,
                               const SigmaType& sigma)
{
    if (sigma <= 0) return math::neg_inf<dist_value_t>;
    dist_value_t z = (x - mean) / sigma;
    return std::exp(-0.5 * z * z) / (sigma * SQRT_TWO_PI);
}

// vss
template <class XType
        , class MeanType
        , class SigmaType
        , class = std::enable_if_t<
            std::is_arithmetic_v<MeanType> &&
            std::is_arithmetic_v<SigmaType>
        > >
inline dist_value_t normal_pdf(const Eigen::MatrixBase<XType>& x,
                               const MeanType& mean,
                               const SigmaType& sigma)
{
    if (sigma <= 0) return math::neg_inf<dist_value_t>;
    dist_value_t z_sq = (x.array() - mean).matrix().squaredNorm() / (sigma * sigma);
    return std::exp(-0.5 * z_sq) / std::pow(sigma * SQRT_TWO_PI, x.size());
}

// vvs
template <class XType
        , class MeanType
        , class SigmaType
        , class = std::enable_if_t<
            std::is_arithmetic_v<SigmaType>
        > >
inline dist_value_t normal_pdf(const Eigen::MatrixBase<XType>& x,
                               const Eigen::MatrixBase<MeanType>& mean,
                               const SigmaType& sigma)
{
    static_assert(ad::util::is_eigen_vector_v<MeanType>);
    assert(x.size() == mean.size());
    if (sigma <= 0) return math::neg_inf<dist_value_t>;
    dist_value_t z_sq = (x.array() - mean.array()).matrix().squaredNorm() / (sigma * sigma);
    return std::exp(-0.5 * z_sq) / std::pow(sigma * SQRT_TWO_PI, x.size());
}

// vsv, vsm
template <class XType
        , class MeanType
        , class SigmaType
        , class = std::enable_if_t<
            std::is_arithmetic_v<MeanType>
        > >
inline dist_value_t normal_pdf(const Eigen::MatrixBase<XType>& x,
                               const MeanType& mean,
                               const Eigen::MatrixBase<SigmaType>& sigma)
{
    if constexpr (ad::util::is_eigen_vector_v<SigmaType>) {
        assert(x.size() == sigma.size());
        if ((sigma.array() <= 0).any()) return math::neg_inf<dist_value_t>;
        dist_value_t z_sq = ((x.array() - mean)/sigma.array()).matrix().squaredNorm();
        return std::exp(-0.5 * z_sq) / (std::pow(SQRT_TWO_PI, x.size()) * sigma.array().prod());

    } else if constexpr (ad::util::is_eigen_matrix_v<SigmaType>) {
        assert(x.size() == sigma.rows());
        Eigen::LLT<Eigen::MatrixXd> llt(sigma);
        if (llt.info() != Eigen::Success) return math::neg_inf<dist_value_t>;
        dist_value_t z_sq = llt.matrixL().solve((x.array() - mean).matrix()).squaredNorm();
        dist_value_t det = llt.matrixL().determinant();
        return std::exp(-0.5 * z_sq) / (std::pow(SQRT_TWO_PI, x.size()) * det);
    }
}

// vvv, vvm
template <class XType
        , class MeanType
        , class SigmaType>
inline dist_value_t normal_pdf(const Eigen::MatrixBase<XType>& x,
                               const Eigen::MatrixBase<MeanType>& mean,
                               const Eigen::MatrixBase<SigmaType>& sigma)
{
    static_assert(ad::util::is_eigen_vector_v<MeanType>);

    if constexpr (ad::util::is_eigen_vector_v<SigmaType>) {
        assert(x.size() == sigma.size());
        assert(x.size() == mean.size());
        if ((sigma.array() <= 0).any()) return math::neg_inf<dist_value_t>;
        dist_value_t z_sq = ((x.array() - mean.array())/sigma.array()).matrix().squaredNorm();
        return std::exp(-0.5 * z_sq) / (std::pow(SQRT_TWO_PI, x.size()) * sigma.array().prod());
    }

    else if constexpr (ad::util::is_eigen_matrix_v<SigmaType>) {
        assert(x.size() == sigma.rows());
        assert(x.size() == mean.size());
        Eigen::LLT<Eigen::MatrixXd> llt(sigma);
        if (llt.info() != Eigen::Success) return math::neg_inf<dist_value_t>;
        dist_value_t z_sq = llt.matrixL().solve((x.array() - mean.array()).matrix()).squaredNorm();
        dist_value_t det = llt.matrixL().determinant();
        return std::exp(-0.5 * z_sq) / (std::pow(SQRT_TWO_PI, x.size()) * det);
    }
}

// sss
template <class XType
        , class MeanType
        , class SigmaType
        , class = std::enable_if_t<
            std::is_arithmetic_v<XType> &&
            std::is_arithmetic_v<MeanType> &&
            std::is_arithmetic_v<SigmaType>
        > >
inline dist_value_t normal_log_pdf(const XType& x,
                                   const MeanType& mean,
                                   const SigmaType& sigma)
{
    if (sigma <= 0) return math::neg_inf<dist_value_t>;
    dist_value_t z = (x - mean) / sigma;
    return -0.5 * z * z - std::log(sigma) - LOG_SQRT_TWO_PI;
}

// vss
template <class XType
        , class MeanType
        , class SigmaType
        , class = std::enable_if_t<
            std::is_arithmetic_v<MeanType> &&
            std::is_arithmetic_v<SigmaType>
        > >
inline dist_value_t normal_log_pdf(const Eigen::MatrixBase<XType>& x,
                           const MeanType& mean,
                           const SigmaType& sigma)
{
    if (sigma <= 0) return math::neg_inf<dist_value_t>;
    dist_value_t z_sq = (x.array() - mean).matrix().squaredNorm() / (sigma * sigma);
    return -0.5 * z_sq - (x.size() * (std::log(sigma) + LOG_SQRT_TWO_PI));
}

// vvs
template <class XType
        , class MeanType
        , class SigmaType
        , class = std::enable_if_t<
            std::is_arithmetic_v<SigmaType>
        > >
inline dist_value_t normal_log_pdf(const Eigen::MatrixBase<XType>& x,
                           const Eigen::MatrixBase<MeanType>& mean,
                           const SigmaType& sigma)
{
    static_assert(ad::util::is_eigen_vector_v<MeanType>);
    assert(x.size() == mean.size());
    if (sigma <= 0) return math::neg_inf<dist_value_t>;
    dist_value_t z_sq = (x.array() - mean.array()).matrix().squaredNorm() / (sigma * sigma);
    return -0.5 * z_sq - (x.size() * (std::log(sigma) + LOG_SQRT_TWO_PI));
}

// vsv, vsm
template <class XType
        , class MeanType
        , class SigmaType
        , class = std::enable_if_t<
            std::is_arithmetic_v<MeanType>
        > >
inline dist_value_t normal_log_pdf(const Eigen::MatrixBase<XType>& x,
                                   const MeanType& mean,
                                   const Eigen::MatrixBase<SigmaType>& sigma)
{
    if constexpr (ad::util::is_eigen_vector_v<SigmaType>) {
        assert(x.size() == sigma.size());
        if ((sigma.array() <= 0).any()) return math::neg_inf<dist_value_t>;
        dist_value_t z_sq = ((x.array() - mean)/sigma.array()).matrix().squaredNorm();
        return -0.5 * z_sq - (x.size() * LOG_SQRT_TWO_PI) - std::log(sigma.array().prod());
    }

    else if constexpr (ad::util::is_eigen_matrix_v<SigmaType>) {
        assert(x.size() == sigma.rows());
        Eigen::LLT<Eigen::MatrixXd> llt(sigma);
        if (llt.info() != Eigen::Success) return math::neg_inf<dist_value_t>;
        dist_value_t z_sq = llt.matrixL().solve((x.array() - mean).matrix()).squaredNorm();
        dist_value_t det = llt.matrixL().determinant();
        return -0.5 * z_sq - (x.size() * LOG_SQRT_TWO_PI) - std::log(det);
    }
}

// vvv, vvm
template <class XType
        , class MeanType
        , class SigmaType>
inline dist_value_t normal_log_pdf(const Eigen::MatrixBase<XType>& x,
                                   const Eigen::MatrixBase<MeanType>& mean,
                                   const Eigen::MatrixBase<SigmaType>& sigma)
{
    if constexpr (ad::util::is_eigen_vector_v<SigmaType>) {
        assert(x.size() == sigma.size());
        assert(x.size() == mean.size());
        if ((sigma.array() <= 0).any()) return math::neg_inf<dist_value_t>;
        dist_value_t z_sq = ((x.array() - mean.array())/sigma.array()).matrix().squaredNorm();
        return -0.5 * z_sq - (x.size() * LOG_SQRT_TWO_PI) - std::log(sigma.array().prod());
    }

    else if constexpr (ad::util::is_eigen_matrix_v<SigmaType>) {
        assert(x.size() == sigma.rows());
        assert(x.size() == mean.size());
        Eigen::LLT<Eigen::MatrixXd> llt(sigma);
        if (llt.info() != Eigen::Success) return math::neg_inf<dist_value_t>;
        dist_value_t z_sq = llt.matrixL().solve((x.array() - mean.array()).matrix()).squaredNorm();
        dist_value_t det = llt.matrixL().determinant();
        return -0.5 * z_sq - (x.size() * LOG_SQRT_TWO_PI) - std::log(det);
    }
}

/////////////////////////////////
// Cauchy Density
/////////////////////////////////

// sss
template <class XType
        , class LocType
        , class ScaleType
        , class = std::enable_if_t<
            std::is_arithmetic_v<XType> &&
            std::is_arithmetic_v<LocType> &&
            std::is_arithmetic_v<ScaleType>
        > >
inline dist_value_t cauchy_log_pdf(const XType& x,
                                   const LocType& loc,
                                   const ScaleType& scale)
{
    auto diff = x - loc;
    return (scale > 0) ? -std::log(scale + diff * diff / scale) : neg_inf<double>;
}

// vss
template <class XType
        , class LocType
        , class ScaleType
        , class = std::enable_if_t<
            std::is_arithmetic_v<LocType> &&
            std::is_arithmetic_v<ScaleType>
        > >
inline dist_value_t cauchy_log_pdf(const Eigen::MatrixBase<XType>& x,
                                   const LocType& loc,
                                   const ScaleType& scale)
{
    bool cond = scale > 0.;
    auto diff = x.array() - loc;
    return cond ? -(scale + (1./scale) * diff * diff).log().sum() :
                  neg_inf<double>;
}

// vvs
template <class XType
        , class LocType
        , class ScaleType
        , class = std::enable_if_t<
            std::is_arithmetic_v<ScaleType>
        > >
inline dist_value_t cauchy_log_pdf(const Eigen::MatrixBase<XType>& x,
                                    const Eigen::MatrixBase<LocType>& loc,
                                    const ScaleType& scale)
{
    bool cond = scale > 0.;
    auto diff = x.array() - loc.array();
    return cond ? -(scale + (1./scale) * diff * diff).log().sum() : neg_inf<double>;
}

// vsv
template <class XType
        , class LocType
        , class ScaleType
        , class = std::enable_if_t<
            std::is_arithmetic_v<LocType>
        > >
inline dist_value_t cauchy_log_pdf(const Eigen::MatrixBase<XType>& x,
                                    const LocType& loc,
                                    const Eigen::MatrixBase<ScaleType>& scale)
{
    bool cond = (scale.array() > 0.).all();
    auto diff = x.array() - loc;
    auto gamma = scale.array();
    return cond ? -(gamma + (1./gamma) * diff * diff).log().sum() : neg_inf<double>;
}

// vvv
template <class XType
        , class LocType
        , class ScaleType>
inline dist_value_t cauchy_log_pdf(const Eigen::MatrixBase<XType>& x,
                                    const Eigen::MatrixBase<LocType>& loc,
                                    const Eigen::MatrixBase<ScaleType>& scale)
{
    bool cond = (scale.array() > 0.).all();
    auto diff = x.array() - loc.array();
    auto gamma = scale.array();
    return cond ? -(gamma + (1./gamma) * diff * diff).log().sum() : neg_inf<double>;
}

/////////////////////////////////
// Uniform Density
/////////////////////////////////

// sss
template <class XType
        , class MinType
        , class MaxType
        , class = std::enable_if_t<
            std::is_arithmetic_v<XType> &&
            std::is_arithmetic_v<MinType> &&
            std::is_arithmetic_v<MaxType>
        > >
inline dist_value_t uniform_pdf(const XType& x,
                                const MinType& min,
                                const MaxType& max)
{
    return (min < x && x < max) ? 1. / (max - min) : 0;
}

// vss
template <class XType
        , class MinType
        , class MaxType
        , class = std::enable_if_t<
            std::is_arithmetic_v<MinType> &&
            std::is_arithmetic_v<MaxType>
        > >
inline dist_value_t uniform_pdf(const Eigen::MatrixBase<XType>& x,
                                const MinType& min,
                                const MaxType& max)
{
    bool cond = (min < x.array()).all() && (x.array() < max).all();
    return cond ? std::pow(1./(max-min), x.size()) : 0;
}

// vvs
template <class XType
        , class MinType
        , class MaxType
        , class = std::enable_if_t<
            std::is_arithmetic_v<MaxType>
        > >
inline dist_value_t uniform_pdf(const Eigen::MatrixBase<XType>& x,
                                const Eigen::MatrixBase<MinType>& min,
                                const MaxType& max)
{
    bool cond = (min.array() < x.array()).all() && (x.array() < max).all();
    return cond ? (1./(max-min.array())).prod() : 0;
}

// vsv
template <class XType
        , class MinType
        , class MaxType
        , class = std::enable_if_t<
            std::is_arithmetic_v<MinType>
        > >
inline dist_value_t uniform_pdf(const Eigen::MatrixBase<XType>& x,
                                const MinType& min,
                                const Eigen::MatrixBase<MaxType>& max)
{
    bool cond = (min < x.array()).all() && (x.array() < max.array()).all();
    return cond ? (1./(max.array()-min)).prod() : 0;
}

// vvv
template <class XType
        , class MinType
        , class MaxType>
inline dist_value_t uniform_pdf(const Eigen::MatrixBase<XType>& x,
                                const Eigen::MatrixBase<MinType>& min,
                                const Eigen::MatrixBase<MaxType>& max)
{
    bool cond = (min.array() < x.array()).all() && (x.array() < max.array()).all();
    return cond ? (1./(max.array()-min.array())).prod() : 0;
}

// sss
template <class XType
        , class MinType
        , class MaxType
        , class = std::enable_if_t<
            std::is_arithmetic_v<XType> &&
            std::is_arithmetic_v<MinType> &&
            std::is_arithmetic_v<MaxType>
        > >
inline dist_value_t uniform_log_pdf(const XType& x,
                                    const MinType& min,
                                    const MaxType& max)
{
    return (min < x && x < max) ? -std::log(max - min) : neg_inf<double>;
}

// vss
template <class XType
        , class MinType
        , class MaxType
        , class = std::enable_if_t<
            std::is_arithmetic_v<MinType> &&
            std::is_arithmetic_v<MaxType>
        > >
inline dist_value_t uniform_log_pdf(const Eigen::MatrixBase<XType>& x,
                                    const MinType& min,
                                    const MaxType& max)
{
    bool cond = (min < x.array()).all() && (x.array() < max).all();
    return cond ?
        static_cast<dist_value_t>(x.size())*(-std::log(max-min)) :
        neg_inf<double>;
}

// vvs
template <class XType
        , class MinType
        , class MaxType
        , class = std::enable_if_t<
            std::is_arithmetic_v<MaxType>
        > >
inline dist_value_t uniform_log_pdf(const Eigen::MatrixBase<XType>& x,
                                    const Eigen::MatrixBase<MinType>& min,
                                    const MaxType& max)
{
    bool cond = (min.array() < x.array()).all() && (x.array() < max).all();
    return cond ? -(max-min.array()).log().sum() : neg_inf<double>;
}

// vsv
template <class XType
        , class MinType
        , class MaxType
        , class = std::enable_if_t<
            std::is_arithmetic_v<MinType>
        > >
inline dist_value_t uniform_log_pdf(const Eigen::MatrixBase<XType>& x,
                                    const MinType& min,
                                    const Eigen::MatrixBase<MaxType>& max)
{
    bool cond = (min < x.array()).all() && (x.array() < max.array()).all();
    return cond ? -(max.array()-min).log().sum() : neg_inf<double>;
}

// vvv
template <class XType
        , class MinType
        , class MaxType>
inline dist_value_t uniform_log_pdf(const Eigen::MatrixBase<XType>& x,
                                    const Eigen::MatrixBase<MinType>& min,
                                    const Eigen::MatrixBase<MaxType>& max)
{
    bool cond = (min.array() < x.array()).all() && (x.array() < max.array()).all();
    return cond ? -(max.array()-min.array()).log().sum() : neg_inf<double>;
}

/////////////////////////////////
// Bernoulli Density
/////////////////////////////////

/**
 * Bernoulli pdf and log pdf (pmf actually).
 * It is defined to clip when p is out of the range [0,1],
 * i.e. if p < 0, then we take p = 0 and
 * if p > 1, then we take p = 1.
 */

// ss
template <class XType
        , class PType
        , class = std::enable_if_t<
            std::is_arithmetic_v<XType> &&
            std::is_arithmetic_v<PType>
        > >
inline dist_value_t bernoulli_pdf(const XType& x,
                                  const PType& p)
{
    if (p <= 0) return (x == 0) + 0.;
    else if (p >= 1) return (x == 1) + 0.;

    if (x == 1) return p;
    else if (x == 0) return 1. - p;
    else return 0.0;
}

// vs
template <class XType
        , class PType
        , class = std::enable_if_t<
            std::is_arithmetic_v<PType>
        > >
inline dist_value_t bernoulli_pdf(const Eigen::MatrixBase<XType>& x,
                                  const PType& p)
{
    double pdf = 1.;
    for (int i = 0; i < x.size(); ++i) {
        pdf *= bernoulli_pdf(x(i), p);
    }
    return pdf;
}

// vv
template <class XType
        , class PType>
inline dist_value_t bernoulli_pdf(const Eigen::MatrixBase<XType>& x,
                                  const Eigen::MatrixBase<PType>& p)
{
    assert(x.size() == p.size());
    double pdf = 1.;
    for (int i = 0; i < x.size(); ++i) {
        pdf *= bernoulli_pdf(x(i), p(i));
    }
    return pdf;
}

// ss
template <class XType
        , class PType
        , class = std::enable_if_t<
            std::is_arithmetic_v<XType> &&
            std::is_arithmetic_v<PType>
        > >
inline dist_value_t bernoulli_log_pdf(const XType& x,
                                      const PType& p)
{
    if (p <= 0) {
        if (x == 0) return 0.;
        else return neg_inf<PType>;
    }
    else if (p >= 1) {
        if (x == 1) return 0.;
        else return neg_inf<PType>;
    }

    if (x == 1) return std::log(p);
    else if (x == 0) return std::log(1. - p);
    else return neg_inf<PType>;
}

// vs
template <class XType
        , class PType
        , class = std::enable_if_t<
            std::is_arithmetic_v<PType>
        > >
inline dist_value_t bernoulli_log_pdf(const Eigen::MatrixBase<XType>& x,
                                      const PType& p)
{
    double logpdf = 0.;
    for (int i = 0; i < x.size(); ++i) {
        logpdf += bernoulli_log_pdf(x(i), p);
    }
    return logpdf;
}

// vv
template <class XType
        , class PType>
inline dist_value_t bernoulli_log_pdf(const Eigen::MatrixBase<XType>& x,
                                      const Eigen::MatrixBase<PType>& p)
{
    assert(x.size() == p.size());
    double logpdf = 0.;
    for (int i = 0; i < x.size(); ++i) {
        logpdf += bernoulli_log_pdf(x(i), p(i));
    }
    return logpdf;
}

/////////////////////////////////
// Wishart Density
// Note: drops unnecessary constant terms
/////////////////////////////////
template <class XType
        , class VType
        , class NType>
inline dist_value_t wishart_log_pdf(const Eigen::MatrixBase<XType>& x,
                                    const Eigen::MatrixBase<VType>& v,
                                    const NType& n)
{
    Eigen::LLT<Eigen::MatrixXd> x_llt(x);
    Eigen::LLT<Eigen::MatrixXd> v_llt(v);
    auto log_det_x = std::log(x_llt.matrixL().determinant());
    auto log_det_v = std::log(v_llt.matrixL().determinant());
    auto tr = v_llt.solve(x).trace();
    dist_value_t p = v.rows();
    return (n - p - 1.) * log_det_x - 0.5 * tr - n * log_det_v;
}

} // namespace math
} // namespace ppl


text:
// Software License for MTL
//
// Copyright (c) 2007 The Trustees of Indiana University.
//               2008 Dresden University of Technology and the Trustees of Indiana University.
//               2010 SimuNova UG (haftungsbeschränkt), www.simunova.com.
// All rights reserved.
// Authors: Peter Gottschling and Andrew Lumsdaine
//
// This file is part of the Matrix Template Library
//
// See also license.mtl.txt in the distribution.

// This test is written by Jan Bos to test the convergence of complex linear systems

#include <boost/numeric/mtl/mtl.hpp>
#include <boost/numeric/itl/itl.hpp>

template <typename Matrix>
void fill(Matrix& m)
{
  double s=19, u=21, p=16, e=5, r=18, l =12;

  std::complex<double> delta(2,1);
  mtl::mat::inserter<Matrix> sm(m);
  // set diagonal
  sm(0,0) << s;
  sm(1,1) << u;
  sm(2,2) << p;
  sm(3,3) << e;
  sm(4,4) << r;
  // below diagonal
  sm(1,0) << l+delta;
  sm(4,0) << l;
  sm(2,1) << l;
  sm(4,1) << l+delta;
  // above diagonal
  sm(0,2) << u;
  sm(0,3) << u+delta;
  //sm(3,4) << u;
  sm(3,4) << u + delta;
}

int main()
{
  // For a more realistic example set size to 1000 or larger
  const int N = 5;

  typedef mtl::compressed2D<std::complex<double> > matrix_type;
  matrix_type                   A(N, N);

  itl::pc::identity<matrix_type>     P(A);
  mtl::dense_vector<std::complex<double> > b(N, std::complex<double>(1,1)), x(N);

  fill(A);
  x= 0;

  itl::cyclic_iteration<double> iter(b, N, 1.e-6, 0.0, 5);
  bicgstab(A, x, b, P, iter);

  return 0;
}


text:
/*
 * parse_COVERT.hpp
 *
 *  Created on: Aug 28, 2017
 *      Author: jit
 */

#ifndef INCLUDE_JITANA_MPI_PARSE_COVERT_HPP_
#define INCLUDE_JITANA_MPI_PARSE_COVERT_HPP_

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/foreach.hpp>
#include <string>
#include <set>
#include <exception>
#include <iostream>
namespace pt = boost::property_tree;

struct covertXML
{
    std::string appName;
    std::string componentName;

    void load(const std::string &filename);
};
//]
//[debug_settings_load
void covertXML::load(const std::string &filename)
{
    // Create empty property tree object
    pt::ptree tree;

    // Parse the XML into the property tree.
    pt::read_xml(filename, tree);

    // Use the throwing version of get to find the debug filename.
    // If the path cannot be resolved, an exception is thrown.
    //m_file = tree.get<std::string>("debug.filename");
    //m_file = tree.get<std::string>("application.components.Component");

    // Use the default-value version of get to find the debug level.
    // Note that the default value is used to deduce the target type.
    //m_level = tree.get("debug.level", 0);

    // Use get_child to find the node containing the modules, and iterate over
    // its children. If the path cannot be resolved, get_child throws.
    // A C++11 for-range loop would also work.
    BOOST_FOREACH(pt::ptree::value_type &v, tree.get_child("application.components")) {
        // The data function is used to access the data stored in a node.
    	std::cout << "First data: " << v.first.data() << '\n';
    	boost::property_tree::ptree subtree = (boost::property_tree::ptree) v.second ;
    	BOOST_FOREACH(boost::property_tree::ptree::value_type &vs,subtree) {
    		std::cout << "\tSub data: " << vs.first.data() <<"\t"<< vs.second.data() << std::endl;
            //std::cout << v.second.data() << std::endl;

    		boost::property_tree::ptree flow = (boost::property_tree::ptree) vs.second ;
    		if (vs.first=="sensitiveFlows"){
    			BOOST_FOREACH(boost::property_tree::ptree::value_type &vs2,flow) {
    				std::cout << "\tSub data: " << vs2.first.data() <<"\t"<< vs2.second.data() << std::endl;
    			}
    		}
        }

    }
}

#endif /* INCLUDE_JITANA_MPI_PARSE_COVERT_HPP_ */

max_stars_repo_name: Mohannadcse/DINA

max_issues_repo_name: Mohannadcse/DINA

max_forks_repo_name: Mohannadcse/DINA


text: #include <boost/accumulators/statistics/rolling_moment.hpp>


text:
#include "Classes.h"
#include <Eigen/Dense>
#include <algorithm>
#include <fstream>
#include <cstdlib>
using namespace std;
using namespace Eigen;

Wireframe Projection2D::create3D(){
    ///
    /// Function that creates the wireframe model from the 2d orthographic views
    ///
    cout << "lets start"<<endl;
    allpoints = determineAllPoints();
    cout <<"adjacencyMatrix point" <<endl;
    // printmatrix(adjacencyMatrix);

    determineIntersectedEdges();
    cout << "determineintersected edges complete "<< endl;
    // printmatrix(adjacencyMatrix);
    cout << "execute corollary 1" <<endl;
    executeCorollary1();
    // printmatrix(adjacencyMatrix);

    cout << "corollary 1 finished chek3edge ==================================================="<< endl;
    chkif3edgesanddefthem();
    // printmatrix(adjacencyMatrix);

    cout<< "chek3edge finished loop starting==================================================="<< endl;
    int numcountwhile = 0;
    while(numofpossibleedge()!=0){
        //function below checks if for a point a possible and definite point are collinear and removes the possible point
        cout << "chekcollinearpossanddef started ================================================================" << endl;
        bool ifcollinearpossanddef = chkcollinearpossanddef();
        // printmatrix(adjacencyMatrix);
        cout << "chkcollinearpossandposs started ================================================================" <<endl;
        bool ifcollinearpossandposs = chkcollinearpossandposs();
        // printmatrix(adjacencyMatrix);
        cout << "chkposshasdefinanother started ================================================================" <<endl;

        bool ifposshasdefinother = chkposshasdefinother();
        // printmatrix(adjacencyMatrix);
        cout << "chk3dgesanddefthem started ================================================================" <<endl;

        chkif3edgesanddefthem();
        // printmatrix(adjacencyMatrix);
        numcountwhile++;
        if(numcountwhile==50){
            cout << "wrong answer"<<endl;
            break;
        }
        // break;
    }
    cout << "numcount is "<< numcountwhile << endl;
    Wireframe answer;
    answer.vertices = allpoints;
    for(auto verticesitr = answer.vertices.begin();verticesitr!=answer.vertices.end();verticesitr++){
        cout << "final points are "<< *verticesitr<<endl;
    }
    int numpoints = allpoints.size();
    for(int i=0;i<numpoints;i++){
        for(int j=0;j<numpoints;j++){
            if(adjacencyMatrix[i][j]==2){
                Edge thisedge;
                thisedge.p1 = * (indextopointmap[i]);
                thisedge.p2 = * (indextopointmap[j]);
                answer.edges.push_back(thisedge);
            }
        }
    }
    int numedges = answer.edges.size();
    for(int i=0;i<numedges;i++){
        cout << "thisedge is " << answer.edges[i].p1 << " is connected to " << answer.edges[i].p2 << endl;
    }
    answer.adjacencyMatrix = adjacencyMatrix;
    cout << "final print of adjacencyMatrix"<<endl;
    printmatrix(answer.adjacencyMatrix);
    numpoints = allpoints.size();
    for(int i=0;i<numpoints;i++){
        vector<int> neighvec = findneighbours(i);
        // cout << "i is "<<i <<endl;
        // cout<< "found neighbours"<<endl;
        int numneigh = neighvec.size();
        for(int j=0;j<numneigh;j++){
            vector<vector<int> > allpaths = giveallpaths(i,neighvec[j]);
            // cout << "given all paths for j = "<<j<<"or neighbour "<<neighvec[j]<<endl;
            // for(int k=0;k<allpaths.size();k++){
            //     for(int l=0;l<allpaths[k].size();l++){
            //         cout << allpaths[k][l] << " ";
            //     }
            //     cout<<endl;
            // }
            // cout<< "printed allpaths"<<endl;
            vector<vector<int> > goodpaths = giveplanarpaths(allpaths);
            // cout << "given all goodpaths for j = "<<j<<endl;
            // for(int k=0;k<goodpaths.size();k++){
            //     for(int l=0;l<goodpaths[k].size();l++){
            //         cout << goodpaths[k][l] << " ";
            //     }
            //     cout<<endl;
            // }
            // cout<< "printed goodpaths"<<endl;
            addsuitablepaths(goodpaths);
            // cout << "added suitable paths for j = "<<j<<endl;
        }
    }
    cout << "printing final faces"<<endl;
    for(int k=0;k<deducedfaces.size();k++){
                for(int l=0;l<deducedfaces[k].size();l++){
                    cout << indextopointmap[deducedfaces[k][l]]->label << " ";
                }
                cout<<endl;
    }
    cout << "printed final faces"<<endl;
    makescadfile();
    return answer;
}

//doublecalculaedpossibleedges has all the edges calculated twice now

vector<Point> Projection2D::determineAllPoints(){
    ///
    /// Function to determine points by intersection of the corresponding points from topview and frontview
    ///
    vector<Point> answer;
    for(auto it=(frontview.vertices.begin());it!=frontview.vertices.end();it++){
        for(auto nestit=(it->points.begin());nestit!=it->points.end();nestit++){
            string thislabel = nestit->label;
            //cout << "iteration on front label "<<thislabel<<endl;
            for(auto itfind=topview.vertices.begin();itfind!=topview.vertices.end();itfind++){
                bool found = false;
                for(auto nestitfind=itfind->points.begin();nestitfind!= itfind->points.end();nestitfind++){
                    string findlabel = nestitfind->label;
                    //cout << "   corresponding iteration on top label " << findlabel <<endl;
                    if(thislabel==findlabel){
                        //cout << "   aloha found the same label"<<endl;
                        found=true;
                        //Point determinedpoint = new Point;
                        Point determinedpoint = determinePoint(*nestit, *nestitfind);
                        //cout << "   determined point is "<< determinedpoint << endl;
                        int sizeanswer = answer.size();
                        determinedpoint.adjacencyIndex=sizeanswer;
                        answer.push_back(determinedpoint);
                        sizeanswer = answer.size();
                        //determinedpoint = answer[sizeanswer-1];

                        //Point * pointerdeterpoint = new Point;
                        //Point * pointerdeterpoint = &(determinedpoint);
                        //cout << "   determined point is "<< * pointerdeterpoint << endl;
                        //cout << "sizeanswer is "<<sizeanswer <<endl;
                        //indextopointmap.insert(make_pair(sizeanswer-1,&(determinedpoint)));
                        // indextopointmap[sizeanswer-1] = & (answer[sizeanswer-1]);
                        //labeltopointmap.insert(make_pair(determinedpoint.label,&(determinedpoint)));
                        // labeltopointmap[determinedpoint.label]=& (answer[sizeanswer-1]);
                        //knownpoints.push_back(&determinedpoint);
                        //cout << "sizeanswer - 1 is" << (sizeanswer-1) <<endl;
                        //cout << "label is " << determinedpoint.label<<endl;
                        //cout << "   isindextopoint working "<< * indextopointmap[sizeanswer-1]<<endl;
                        //cout << "   islabeltopoint working "<< * labeltopointmap[determinedpoint.label]<<endl;
                        break;
                    }

                }
                if(found==true){
                    break;
                }
            }

        }

    }
    // cout << "lets make the indextopointmap ============================================================="<< endl;
    int numpoints = answer.size();
    for(vector<Point>::iterator iteranswer = answer.begin();iteranswer!=answer.end();iteranswer++){
        // cout<< "adding " << * iteranswer << endl;
        indextopointmap.insert(make_pair(iteranswer->adjacencyIndex,&(* iteranswer)));
    }
    for(vector<Point>::iterator iteranswer = answer.begin();iteranswer!=answer.end();iteranswer++){
        // cout<< "adding " << * iteranswer << endl;
        labeltopointmap.insert(make_pair(iteranswer->label,&(* iteranswer)));
    }
    //adjacencyMatrix(numpoints,temp);
    // cout << "iterating over labeltopointmap========================================================================================" <<endl;
    // for(map<string,Point *>::iterator it = labeltopointmap.begin();it!=labeltopointmap.end();it++){
    //     cout << it->first << " " << * (it->second) << endl;
    // }
    // cout << "iterating over indextopointmap========================================================================================" <<endl;

    // for(map<int,Point *>::iterator it = indextopointmap.begin();it!=indextopointmap.end();it++){
    //     cout << it->first << " " << * (it->second) << endl;
    // }
    for(int i=0;i<numpoints;i++){
        // cout << "answer[i] is " << answer[i]<<endl;
        // cout << "check for label to point" << * labeltopointmap.at(answer[i].label)<< endl;
        // cout << "check for int to point" << * indextopointmap.at(answer[i].adjacencyIndex)<< endl;

        vector<int> temp(numpoints,0);
        adjacencyMatrix.push_back(temp);
    }

    return answer;
}

Point Projection2D::determinePoint(Point pfront, Point ptop) {
    ///
    /// This function extends the points from the top view and front view to give the 3D projection of the Point
    ///
    Point coincidingpoint;
    if(!(pfront.x == ptop.x)){
        //throw exception that not possible
        cout << "not possible projection" << endl;
    }
    coincidingpoint.setCoordinatesAndLabel(ptop.x,ptop.y,pfront.z,ptop.label);
    return coincidingpoint;
}

pair <vector<Edge>, vector<vector<int> > > Projection2D::determinePossibleEdges(Point vertex, vector<Point> *topneighbourptr, vector<Point> *frontneighbourptr) {
    ///
    /// This function determines the edges containing the Point vertex as one of the endpoints
    /// By interpreting its neighbours from the top view and front view
    ///
    vector<Edge> answer;
    vector<vector<int> > thismatrix;
    int numpoints = allpoints.size();
    for(int i=0;i<numpoints;i++){
        vector<int> temp(numpoints,0);
        thismatrix.push_back(temp);
    }

    vector<Point> intersection;
    vector<Point> topneighbour = * (topneighbourptr);

    vector<Point> frontneighbour = * (frontneighbourptr);
    // cout<< "secondneighbours of consideration are --------------------------------------------"<< endl;
    // for(int i=0;i<frontneighbour.size();i++){
    //     cout << frontneighbour[i] << endl;
    // }
    for(auto topneighbouritr=topneighbourptr->begin();topneighbouritr!=topneighbourptr->end();topneighbouritr++){
        auto correspondingpointinfrontasptr = find_if(frontneighbourptr->begin(),frontneighbourptr->end(),[topneighbouritr](Point p)->bool{
            return(p.label==topneighbouritr->label);
        });
        if(correspondingpointinfrontasptr!=frontneighbourptr->end()){
            // cout<< "the collided point will be "<< correspondingpointinfrontasptr->label<<endl;
            Point collidedpoint = * labeltopointmap[correspondingpointinfrontasptr->label];
            intersection.push_back(collidedpoint);
        }
    }
    int numintersectionp = intersection.size();
    // for(int i=0;i<numintersectionp;i++){
    //     cout << "intersection points are "<< intersection[i]<<endl;
    // }
    int numpointsaa = allpoints.size();

    for(auto intersectionitr = intersection.begin();intersectionitr!=intersection.end();intersectionitr++){
        Edge tempedge;
        tempedge.p1 = vertex;
        tempedge.p2 = *(labeltopointmap[intersectionitr->label]);
        //int i = vertex.adjacencyIndex;
        int i = labeltopointmap[vertex.label]->adjacencyIndex;
        int j = labeltopointmap[intersectionitr->label]->adjacencyIndex;
        //adjacencyMatrix[i][j]=adjacencyMatrix[i][j]+1;
        //adjacencyMatrix[j][i]=adjacencyMatrix[j][i]+1;
        thismatrix[i][j] = 1;
        thismatrix[j][i] = 1;
        answer.push_back(tempedge);
    }

    return make_pair(answer,thismatrix);

}

void Projection2D::determineIntersectedEdges(){
    ///
    ///Funtion to determine all the  possible edges for all the points
    ///
    for(auto pointitr=allpoints.begin();pointitr!=allpoints.end();pointitr++){
        // cout << "-----------------------------------------------------------------------" <<endl;
        // cout << "iterating on point "<< pointitr->label <<endl;
        // cout << "-----------------------------------------------------------------------" <<endl;
        vector<Point> topneighbours = topview.possibleNeighbours(* pointitr);
        // cout << "-----------------------------------------------------------------------" <<endl;
        // cout << "topneighbours are "<<endl;
        // for(int i=0;i<topneighbours.size();i++){
        //     cout << topneighbours[i]<< endl;
        // }
        // cout << "-----------------------------------------------------------------------" <<endl;
        vector<Point> frontneighbours = frontview.possibleNeighbours(* pointitr);
        // cout << "-----------------------------------------------------------------------" <<endl;
        // cout << "frontneighbours are "<<endl;
        // for(int i=0;i<frontneighbours.size();i++){
        //     cout << frontneighbours[i]<< endl;
        // }
        // cout << "-----------------------------------------------------------------------" <<endl;
        vector<Point> sideneighbours = sideview.possibleNeighbours(* pointitr);
        // cout << "-----------------------------------------------------------------------" <<endl;
        // cout << "sideneighbours are "<<endl;
        // for(int i=0;i<sideneighbours.size();i++){
        //     cout << sideneighbours[i]<< endl;
        // }
        // cout << "-----------------------------------------------------------------------" <<endl;
        // cout<< "we have to intersect topandfront ------------------------------"<<endl;
        // vector<Edge> topAndFront = determinePossibleEdges(*pointitr,&topneighbours,&frontneighbours).first;
        auto topandfrontmatrix = determinePossibleEdges(*pointitr,&topneighbours,&frontneighbours).second;
        // cout<< "topandfronthasbeenintersected -------------------"<<endl;

        // cout<< "we have to intersect sideandfront ------------------------------"<<endl;

        // vector<Edge> sideAndFront = determinePossibleEdges(*pointitr,&sideneighbours,&frontneighbours).first;
        auto sideandfrontmatrix = determinePossibleEdges(*pointitr,&sideneighbours,&frontneighbours).second;
        // cout << "sideandfronthasbeenintersected -----------------------"<<endl;

        // cout<< "we have to intersect topandside ------------------------------"<<endl;

        // vector<Edge> sideAndFront = determinePossibleEdges(*pointitr,&sideneighbours,&frontneighbours).first;
        auto topandsidematrix = determinePossibleEdges(*pointitr,&topneighbours,&sideneighbours).second;
        // cout << "topandfronthasbeenintersected -----------------------"<<endl;

        int numpoints = allpoints.size();
        for(int i = 0; i<numpoints;i++){
            for(int j=0;j<numpoints;j++){
                if(topandfrontmatrix[i][j]==1 && sideandfrontmatrix[i][j]==1 && topandsidematrix[i][j]==1){
                    adjacencyMatrix[i][j] =1;
                }else{
                    //adjacencyMatrix[i][j]=0;
                }
            }
        }

    }
}

void Projection2D::executeCorollary1onebyone(OrthoProjection* view1, OrthoProjection* view2, OrthoProjection* view3){
    ///
    /// Function to execute corollary one of superimposed points in one view and possible edge in other view for each view
    ///
    for(auto clusteritr = view1->vertices.begin();clusteritr!=view1->vertices.end();clusteritr++){
        if(clusteritr->points.size()==2){
            bool isconnectedinotherview2 = view2->isConnected(clusteritr->points[0].label,clusteritr->points[1].label);
            bool isconnectedinotherview3 = view3->isConnected(clusteritr->points[0].label,clusteritr->points[1].label);
            if(isconnectedinotherview2 && isconnectedinotherview3){
                int i = labeltopointmap[clusteritr->points[0].label]->adjacencyIndex;
                int j = labeltopointmap[clusteritr->points[1].label]->adjacencyIndex;
                if(adjacencyMatrix[i][j]==1 || adjacencyMatrix[j][i]==1){
                    adjacencyMatrix[i][j] = 2;
                    adjacencyMatrix[j][i] = 2;
                }
            }
        }
    }
}
void Projection2D::executeCorollary1(){
    ///
    /// Function to execute corollary one for all views
    ///
    executeCorollary1onebyone(&topview,&frontview,&sideview);

    executeCorollary1onebyone(&frontview,&topview,&sideview);
    // executeCorollary1onebyone(&frontview,&sideview);
    executeCorollary1onebyone(&sideview,&frontview,&topview);
    // executeCorollary1onebyone(&topview,&sideview);
    // executeCorollary1onebyone(&sideview,&topview);

}
void Projection2D::chkif3edgesanddefthem(){
    ///
    /// Function to check if there are only three possible edges and then make them the final edge
    ///
    int numpointsall = allpoints.size();
    for(int i=0; i<numpointsall;i++){
        int numedge = count_if(adjacencyMatrix[i].begin(),adjacencyMatrix[i].end(),[](int v)->bool{
            return(v>0);
        });
        // cout << "for int i " << i << " " << numedge << endl;
        if(numedge==3){
            for(int j=0;j<numpointsall;j++){
                if(adjacencyMatrix[i][j]==1){
                    adjacencyMatrix[i][j] = 2;
                    adjacencyMatrix[j][i] = 2;
                }
            }
        }
    }
}
int Projection2D::numofpossibleedge(){
    ///
    /// Function to determine possible edges
    ///
    int num1=0;
    int numpointsall = allpoints.size();
    for(int i=0;i<numpointsall;i++){
        num1 = num1 + count(adjacencyMatrix[i].begin(),adjacencyMatrix[i].end(),1);
    }
    return num1;
}
bool Projection2D::chkcollinearpossanddef(){
    ///
    /// check if a point has two collinear points as its edge, one being definite and other being possible, if so, remove the possible edge
    ///
    int numpoints = allpoints.size();
    bool ret =false;
    for(int i=0;i<numpoints;i++){
        Point * thispoint = & (allpoints[i]);

        vector<int> thisvec = adjacencyMatrix[i];
        int numposs = count(thisvec.begin(),thisvec.end(),1);
        int numdef = count(thisvec.begin(),thisvec.end(),2);
        if(numposs>0 && numdef>0){
            vector<int> defindexvec;
            for(int j=0;j<numpoints;j++){
                if(thisvec[j]==2){
                    defindexvec.push_back(j);
                }
            }
            for(int j=0;j<numpoints;j++){
                if(thisvec[j]==1){
                    Point * posspoint = (indextopointmap[j]);
                    for(auto defindexvecitr = defindexvec.begin();defindexvecitr!=defindexvec.end();defindexvecitr++){
                        Point * defpoint = indextopointmap[(* defindexvecitr)];
                        bool iscollinear = thispoint->checkcollinear(posspoint, defpoint);
                        if(iscollinear){
                            adjacencyMatrix[i][j] = 0;
                            adjacencyMatrix[j][i] = 0;
                            ret = true;
                            break;
                        }
                    }
                }
            }
        }
    }
    return ret;
}
bool Projection2D::chkcollinearpossandposs(){
    ///
    /// if two points are collinear and possible edges only one of them could be definite, definite being the closest point,
    /// Given that the point whose neighbours are being calculated lies on one end
    ///
    // cout << "poss and poss started "<< endl;
    int numpoints = allpoints.size();
    bool ret =false;
    for(int i=0;i<numpoints;i++){
        Point * thispoint = new Point;
        thispoint = & (allpoints[i]);
        // cout << "point of consideration is " << *thispoint << endl;
        vector<int> thisvec = adjacencyMatrix[i];
        int numposs = count(thisvec.begin(),thisvec.end(),1);
        int numdef = count(thisvec.begin(),thisvec.end(),2);
        // cout << "numpos and numdef are " << numposs << " " << numdef << endl;
        if(numposs>=2){
            for(int j=0;j<numpoints;j++){
                if(adjacencyMatrix[i][j]==1){
                    for(int k=j+1;k<numpoints;k++){
                        if(adjacencyMatrix[i][k]==1){
                            // cout << "j and k are " << j << " " << k << endl;
                            if(thispoint->checkcollinear(indextopointmap[j],indextopointmap[k])){
                                // cout << "j and k are collinear "<< endl;
                                Point * jpointptr = new Point;
                                Point * kpointptr = new Point;
                                jpointptr = indextopointmap[j];
                                kpointptr = indextopointmap[k];
                                // cout << "jpoint is " << *jpointptr << endl;
                                // cout << "kpoint is " << *kpointptr << endl;
                                for(int it=0;it<3;it++){
                                    // cout << "it is " <<it << endl;
                                    vector<Point> topcluster;
                                    if(it==0){
                                        topcluster =topview.sameclusterpointsincluded(*thispoint);
                                    }else if(it==1){
                                        topcluster = frontview.sameclusterpointsincluded(*thispoint);
                                    }else{
                                        topcluster = sideview.sameclusterpointsincluded(*thispoint);
                                    }
                                    // cout << "topcluster computed" <<endl;
                                    if(topcluster.size()==0){
                                        continue;
                                    }
                                    // cout << "topcluster size isnt 0" << endl;
                                    auto jiterator = find_if(topcluster.begin(),topcluster.end(),[jpointptr](Point p)->bool{
                                        return(jpointptr->label==p.label);
                                    });
                                    if(jiterator!=topcluster.end()){
                                        // cout << "it must enter in this j"<< endl;
                                        auto kiterator = find_if(topcluster.begin(),topcluster.end(),[kpointptr](Point p)->bool{
                                            return(kpointptr->label==p.label);
                                        });
                                        if(kiterator!=topcluster.end()){
                                            // cout << "it must enter in this k"<< endl;
                                            int topclustersize = topcluster.size();
                                            // cout << "end and start of this cluster are "<< topcluster[0].label << " and "<< topcluster[topclustersize-1].label << endl;
                                            if((topcluster[0].label)==(thispoint->label) || (topcluster[topclustersize-1].label)==(thispoint->label)){
                                                // cout << "do not change the end part "<< endl;
                                                Vector3d a1(thispoint->x,thispoint->y,thispoint->z);
                                                Vector3d a2(jpointptr->x,jpointptr->y,jpointptr->z);
                                                Vector3d a3(kpointptr->x,kpointptr->y,kpointptr->z);
                                                double dis1 = (a2-a1).norm();
                                                double dis2 = (a3-a1).norm();
                                                if(dis1<dis2){
                                                    adjacencyMatrix[i][j]=2;
                                                    adjacencyMatrix[j][i]=2;
                                                    adjacencyMatrix[i][k]=0;
                                                    adjacencyMatrix[k][i]=0;
                                                }else{
                                                    adjacencyMatrix[i][j]=0;
                                                    adjacencyMatrix[j][i]=0;
                                                    adjacencyMatrix[i][k]=2;
                                                    adjacencyMatrix[k][i]=2;
                                                }
                                                ret = true;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    return ret;
}
bool Projection2D::chkposshasdefinother(){
    ///
    /// Function to check if a possible edge point has definite neighbours with other edges, if so remove them
    ///
    int numpoints = allpoints.size();
    bool ret =false;
    for(int i=0;i<numpoints;i++){
        Point * thispoint = & (allpoints[i]);
        //vector<int> thisvec = adjacencyMatrix[i];
        vector<int> posspointsvec,defpointsvec;
        for(int j=0;j<numpoints;j++){
            if(adjacencyMatrix[i][j]==1){
                posspointsvec.push_back(j);
            }else if(adjacencyMatrix[i][j]==2){
                defpointsvec.push_back(j);
            }
        }
        if(defpointsvec.size()<2){
            continue;
        }
        for(int j=0;j<posspointsvec.size();j++){
            int thisposspointindex = posspointsvec[j];
            int numberofintersections = 0;
            for(int k=0;k<defpointsvec.size();k++){
                if(adjacencyMatrix[thisposspointindex][defpointsvec[k]]==2){
                    numberofintersections++;
                }
            }
            if(numberofintersections>=2){
                adjacencyMatrix[i][thisposspointindex]=0;
                adjacencyMatrix[thisposspointindex][i]=0;
                ret =true;
            }
        }
    }
    return ret;
}

void Projection2D::printmatrix(vector<vector<int> > thisone){
    ///
    /// Function to print the matrix
    ///
    int tempint = allpoints.size();
        for(int i=-1;i<tempint;i++){
        for(int j=-1;j<tempint;j++){
            if(i==-1){
                if(j!=-1){
                    cout << allpoints[j].label << " ";
                    if(j==allpoints.size()-1){
                        cout << endl;
                    }
                }else{
                    cout << "  ";
                }
            }else{
                if(j!=-1){
                    cout << thisone[i][j]<< " ";
                    if(j == allpoints.size()-1){
                        cout << endl;
                    }
                }else{
                    cout << allpoints[i].label << " ";
                }

            }
        }
    }
}

vector<int> Projection2D::findneighbours(int thispoint){
    ///
    /// function to find the neighbours of a point
    ///

    vector<int> neighvec;
    int numpoints = allpoints.size();
    for(int i = 0 ;i<numpoints;i++){
        if(adjacencyMatrix[thispoint][i]==2){
            neighvec.push_back(i);
        }
    }
    return neighvec;
}
vector<vector<int> > Projection2D::giveallpaths(int start, int dest){
    ///
    /// function to give all the possible paths from start to destination
    ///
    int numpoints = allpoints.size();
    vector<vector<int> > allpaths;
    bool *visited = new bool[numpoints];
    int *path = new int[numpoints];
    int path_index = 0;
    for (int i = 0; i < numpoints; i++)
        visited[i] = false;
    giveAllPathsUtil(start, dest, visited, path, path_index, allpaths);
    return allpaths;
}

void Projection2D::giveAllPathsUtil(int u, int d, bool visited[], int path[], int &path_index, vector<vector<int> > &allpaths){
    ///
    /// function to give all possible paths from u to d
    ///
    visited[u] = true;
    path[path_index] = u;
    path_index++;
    if (u == d)
    {
        // vector<int> thispath(path, path + path_index);
        vector<int> thispath;
        for(int i = 0;i<path_index;i++){
            thispath.push_back(path[i]);
        }
        allpaths.push_back(thispath);
    }
    else // If current vertex is not destination
    {
        // Recur for all the vertices adjacent to current vertex
        vector<int> neighvec = findneighbours(u);
        for(auto iter= neighvec.begin();iter!=neighvec.end();iter++){
            if(!visited[*iter]){
                giveAllPathsUtil(*iter, d, visited, path, path_index,allpaths);
            }
        }
    }
    path_index--;
    visited[u] = false;
}

vector<vector<int> > Projection2D::giveplanarpaths(vector<vector<int> > allpaths){
    ///
    /// function to filter out non-planar paths
    ///
    vector<vector<int> > filteredpaths;
    int numallpaths = allpaths.size();
    for(int i=0;i<numallpaths;i++){
        vector<int> thispath = allpaths[i];
        if(thispath.size()==3){
            filteredpaths.push_back(thispath);
            // cout<<"adding path of lenght 3"<<endl;
        }else if(thispath.size()>3){
            bool isplanarbool= isplanar(thispath);
            if(isplanarbool){
                filteredpaths.push_back(thispath);
            }
        }

    }
    return filteredpaths;
}

bool Projection2D::isplanar(vector<int> thispath){
    ///
    /// function to check if a path is planar or not
    ///
    bool isplanar=true;
    int thispathsize = thispath.size();
    // cout<<"vector of consideration is "<<endl;
    // for(int i=0;i<thispathsize;i++){
    //     cout << thispath[i]<<" ";
    // }
    // cout <<endl;
    Point firstpoint = * (indextopointmap[thispath[0]]);
    Point secondpoint = * (indextopointmap[thispath[1]]);
    Point thirdpoint = * (indextopointmap[thispath[2]]);
    Vector3d firstpointvec(firstpoint.x,firstpoint.y,firstpoint.z);
    Vector3d secondpointvec(secondpoint.x,secondpoint.y,secondpoint.z);
    Vector3d thirdpointvec(thirdpoint.x,thirdpoint.y,thirdpoint.z);
    Vector3d firstedge = secondpointvec-firstpointvec;
    Vector3d secondedge = thirdpointvec-secondpointvec;
    Vector3d normal = firstedge.cross(secondedge);
    for(int i=3;i<thispathsize;i++){
        Point thispoint = * (indextopointmap[thispath[i]]);
        Point prevpoint = * (indextopointmap[thispath[i-1]]);
        Vector3d thispointvec(thispoint.x,thispoint.y,thispoint.z);
        Vector3d prevpointvec(prevpoint.x,prevpoint.y,prevpoint.z);
        Vector3d thisedge = thispointvec-prevpointvec;
        double dotproduct = normal.dot(thisedge);
        if(dotproduct==0.0){
            continue;
        }else{
            isplanar=false;
            break;
        }
    }
    // cout <<"was this planar "<<isplanar<<endl;
    return isplanar;
}

void Projection2D::addsuitablepaths(vector<vector<int> > goodpaths){
    ///
    /// function to add planar paths to faces
    ///
    for(auto iter = goodpaths.begin();iter!= goodpaths.end();iter++){
        if(!ispresent(*iter)){
            deducedfaces.push_back(*iter);
        }
    }
}

bool Projection2D::ispresent(vector<int> thispath){
    ///
    /// function to check if the given face has already been added or not
    ///
    bool ispresent = false;
    for(auto iter = deducedfaces.begin();iter!=deducedfaces.end();iter++){
        if(isequavalent(*iter,thispath)){
            ispresent=true;
            break;
        }else{
            continue;
        }
    }
    return ispresent;
}

bool Projection2D::isequavalent(vector<int> vec1,vector<int> vec2){
    ///
    /// function to check whether two representation of vectors are equal
    ///
    bool isequavalent = false;
    if(vec1.size()==vec2.size()){
        sort(vec1.begin(),vec1.end());
        sort(vec2.begin(),vec2.end());
        for(int i=0;i<vec1.size();i++){
            if(vec1[i]!=vec2[i]){
                return false;
            }
        }
        isequavalent=true;
        return true;
    }
    return isequavalent;
}
void Projection2D::makescadfile(){
    ///
    /// function to make scad file, stl, render scad file and then run it
    ///
    ofstream scadfile ("object.scad");
    if(scadfile.is_open()){
        // scadfile<< "cube([2,3,9]);";
        scadfile <<"ObjectPoints = [\n";
        int numpoints = allpoints.size();
        for(int i=0;i<numpoints;i++){
            Point temp = allpoints[i];
            scadfile<<"    [ "<<temp.x<<", "<<temp.y<<", "<<temp.z<<" ]";
            if(i!=numpoints-1){
                scadfile<<",";
            }else{
                scadfile<<"];";
            }
            scadfile<<  "  //"<<i<<"\n";
        }
        scadfile <<"\n";
        scadfile << "ObjectFaces = [\n";
        int numfaces = deducedfaces.size();
        for(int i=0;i<numfaces;i++){
            scadfile<<"[";
            for(int j=0;j<deducedfaces[i].size();j++){
                scadfile<<deducedfaces[i][j];
                if(j!=deducedfaces[i].size()-1){
                    scadfile<<",";
                }
            }
            scadfile<< "]";
            if(i!=numfaces-1){
                scadfile<<",\n";
            }else{
                scadfile<<"];\n";
            }
        }
        scadfile<< "polyhedron( ObjectPoints, ObjectFaces );";
        scadfile.close();
        system("openscad -o object.stl object.scad");
        ofstream renderfile ("render.scad");
        if(renderfile.is_open()){
            renderfile<< "render(){import(\"object.stl\");}";
            renderfile.close();
            system("openscad render.scad");
        }else{
            cout<< "unable to render the stl";
        }
    }else{
        cout<< "unable to open file"<<endl;
    }

}


text:
/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/

#ifndef _CAIROCANVAS_SPRITEDEVICEHELPER_HXX
#define _CAIROCANVAS_SPRITEDEVICEHELPER_HXX

#include <com/sun/star/awt/Rectangle.hpp>
#include <com/sun/star/rendering/XGraphicDevice.hpp>
#include <com/sun/star/rendering/XBufferController.hpp>

#include <boost/utility.hpp>

#include <vcl/window.hxx>
#include <vcl/bitmap.hxx>

#include "cairo_cairo.hxx"
#include "cairo_devicehelper.hxx"

/* Definition of DeviceHelper class */

namespace cairocanvas
{
    class SpriteCanvas;
    class SpriteCanvasHelper;

    class SpriteDeviceHelper : public DeviceHelper
    {
    public:
        SpriteDeviceHelper();

        void init( Window&                   rOutputWindow,
                   SpriteCanvas&			 rSpriteCanvas,
                   const ::basegfx::B2ISize& rSize,
                   bool                      bFullscreen );

        /// Dispose all internal references
        void disposing();

        // XWindowGraphicDevice
        ::sal_Int32 createBuffers( ::sal_Int32 nBuffers );
        void 		destroyBuffers(  );
        ::sal_Bool  showBuffer( bool, ::sal_Bool );
        ::sal_Bool  switchBuffer( bool, ::sal_Bool bUpdateAll );

        ::com::sun::star::uno::Any isAccelerated() const;
        ::com::sun::star::uno::Any getDeviceHandle() const;
        ::com::sun::star::uno::Any getSurfaceHandle() const;

        void notifySizeUpdate( const ::com::sun::star::awt::Rectangle& rBounds );
        void setSize( const ::basegfx::B2ISize&	rSize );

        ::cairo::SurfaceSharedPtr getSurface();
        ::cairo::SurfaceSharedPtr getBufferSurface();
        ::cairo::SurfaceSharedPtr getWindowSurface();
        ::cairo::SurfaceSharedPtr createSurface( const ::basegfx::B2ISize& rSize, ::cairo::Content aContent = CAIRO_CONTENT_COLOR_ALPHA );
        ::cairo::SurfaceSharedPtr createSurface( BitmapSystemData& rData, const Size& rSize );
        const ::basegfx::B2ISize& getSizePixel();
        void flush();

    private:
        /// Pointer to sprite canvas (owner of this helper), needed to create bitmaps
        SpriteCanvas*		      mpSpriteCanvas;

        ::cairo::SurfaceSharedPtr mpBufferSurface;

        ::basegfx::B2ISize        maSize;
        bool                      mbFullScreen;
    };
}

#endif

ext: hxx

max_stars_repo_name: Grosskopf/openoffice

max_issues_repo_name: Grosskopf/openoffice

max_forks_repo_name: Grosskopf/openoffice