<commit_before>// $Id: Box3_test.C,v 1.11 2000/07/26 16:49:46 amoll Exp $
#include <BALL/CONCEPT/classTest.h>

///////////////////////////
#	include <BALL/MATHS/box3.h>
#	include <BALL/MATHS/vector3.h>
///////////////////////////

START_TEST(class_name, "$Id: Box3_test.C,v 1.11 2000/07/26 16:49:46 amoll Exp $")

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

using namespace BALL;
using namespace std;

CHECK(TVector3::BALL_CREATE(TBox3<T>))
	Vector3 v1(1.0, 2.0, 3.0), v2(1.0, 2.0, 3.0);
	Vector3 v0;
	Box3 v(v1, v2);
	Box3* v_ptr = (Box3*)v.create(false, true);
	TEST_EQUAL(v_ptr->a == v0, true)
	TEST_EQUAL(v_ptr->b == v0, true)
	delete v_ptr;
	v_ptr = (Box3*)v.create();
	TEST_EQUAL(v_ptr->a == v1, true)
	TEST_EQUAL(v_ptr->b == v2, true)
	delete v_ptr;
RESULT

CHECK(TBox3::TBox3())
  Box3* box;
	box = new Box3();
	TEST_NOT_EQUAL(box, 0)
RESULT

Box3 box, box2;
Vector3 v1, v2, v3, v4;
float a = 1.0, b = 2.0, c = 3.0,
			d = 6.0, e = 5.0, f = 4.0;
float a1, b1, c1, d1, e1, f1;

v1 = Vector3(1.0, 2.0, 3.0);
v2 = Vector3(6.0, 5.0, 4.0);

String filename;
using std::ofstream;
using std::ios;

//also test for TBox3::get(T& ax, T& ay, T& az, T& bx, T& by, T& bz) const
CHECK(TBox3::TBox3(const T& ax, const T& ay, const T& az, const T& bx, const T& by, const T& bz))
	box = Box3(a, b, c, d, e, f);
	float a1, b1, c1, d1, e1, f1;
	box.get(a1, b1, c1, d1, e1, f1);
	TEST_REAL_EQUAL(a, a1)
	TEST_REAL_EQUAL(b, b1)
	TEST_REAL_EQUAL(c, c1)
	TEST_REAL_EQUAL(d, d1)
	TEST_REAL_EQUAL(e, e1)
	TEST_REAL_EQUAL(f, f1)
RESULT

CHECK(TBox3::TBox3(const TBox3<T>& box, bool /* deep */))
	box = Box3(v1, v2);
	box2 = Box3(box);
	float a1, b1, c1, d1, e1, f1;
	box2.get(a1, b1, c1, d1, e1, f1);
	TEST_REAL_EQUAL(a, a1)
	TEST_REAL_EQUAL(b, b1)
	TEST_REAL_EQUAL(c, c1)
	TEST_REAL_EQUAL(d, d1)
	TEST_REAL_EQUAL(e, e1)
	TEST_REAL_EQUAL(f, f1)
RESULT

CHECK(TBox3::TBox3(const TVector3<T>& a, const TVector3<T>& b))
	box = Box3(v1, v2);
	box.get(a1, b1, c1, d1, e1, f1);
	TEST_REAL_EQUAL(a, a1)
	TEST_REAL_EQUAL(b, b1)
	TEST_REAL_EQUAL(c, c1)
	TEST_REAL_EQUAL(d, d1)
	TEST_REAL_EQUAL(e, e1)
	TEST_REAL_EQUAL(f, f1)
RESULT

CHECK(TBox3::getSurface() const )
	box = Box3(v1, v2);
	TEST_REAL_EQUAL(box.getSurface(), 46.0)
RESULT

CHECK(TBox3::getVolume() const )
	box = Box3(v1, v2);
	TEST_REAL_EQUAL(box.getVolume(), 15.0)
RESULT

CHECK(TBox3::getWidth() const )
	box = Box3(v1, v2);
	TEST_REAL_EQUAL(box.getWidth(), 5.0)
RESULT

CHECK(TBox3::getHeight() const )
	box = Box3(v1, v2);
	TEST_REAL_EQUAL(box.getHeight(), 3.0)
RESULT

CHECK(TBox3::getDepth() const )
	box = Box3(v1, v2);
	TEST_REAL_EQUAL(box.getDepth(), 1.0)
RESULT

CHECK(TBox3::join(const TBox3& box))
	box = Box3(v1, v2);
	v3 = Vector3(101.0, 102.0, 103.0);
	v4 = Vector3(104.0, 105.0, 106.0);
	box2 = Box3(v3, v4);
	box.join(box2);
	box.get(a1, b1, c1, d1, e1, f1);
	TEST_REAL_EQUAL(1, a1)
	TEST_REAL_EQUAL(2, b1)
	TEST_REAL_EQUAL(3, c1)
	TEST_REAL_EQUAL(104, d1)
	TEST_REAL_EQUAL(105, e1)
	TEST_REAL_EQUAL(106, f1)
RESULT

CHECK(TBox3::bool operator == (const TBox3& box) const )
	box = Box3(v1, v2);
	box2 = Box3(v3, v4);
	TEST_EQUAL(box == box2, false)
	box2 = Box3(v1, v2);
	TEST_EQUAL(box == box2, true)
RESULT

CHECK(TBox3::bool operator != (const TBox3& box) const )
	box = Box3(v1, v2);
	box2 = Box3(v3, v4);
	TEST_EQUAL(box != box2, true)
	box2 = Box3(v1, v2);
	TEST_EQUAL(box != box2, false)
RESULT

CHECK(TBox3::isValid() const )
	box = Box3(v1, v2);
	TEST_EQUAL(box.isValid(), true)
RESULT

CHECK(TBox3::set(const TBox3<T>& box, bool /* deep */))
	box = Box3(v1, v2);
	box2.set(box);
	TEST_EQUAL(box == box2, true)
RESULT

CHECK(TBox3::set(const T& ax, const T& ay, const T& az, const T& bx, const T& by, const T& bz))
	box = Box3(v1, v2);
	box2.set(1.0, 2.0, 3.0, 6.0, 5.0, 4.0);
	TEST_EQUAL(box == box2, true)
RESULT

CHECK(TBox3::get(TBox3<T>& box, bool deep) const )
	box = Box3(v1, v2);
	box.get(box2);
	TEST_EQUAL(box == box2, true)
RESULT

CHECK(TBox3::get(TVector3& lower, TVector3& upper) const)
	Box3 box;
	box2.get(box);
	TEST_EQUAL(box == box2, true)
RESULT

CHECK(TBox3::get(T& ax, T& ay, T& az, T& bx, T& by, T& bz) const )
	box = Box3(v1, v2);
	box.get(a1, b1, c1, d1, e1, f1);
	box2.set(a1, b1, c1, d1, e1, f1);
	TEST_EQUAL(box == box2, true)
RESULT

CHECK(TBox3::dump(std::ostream& s = std::cout, Size depth = 0) const )
	Box3 v(1.0, 2.0, 3.0, 4.0, 5.0, 6.0);
  String filename;
	NEW_TMP_FILE(filename)
	std::ofstream outfile(filename.c_str(), File::OUT);
	v.dump(outfile);
	outfile.close();
	TEST_FILE(filename.c_str(), "data/Box3_test.txt", true)
RESULT

CHECK(std::istream& operator >> (std::istream& s, TBox3<T>& Box3))
	std::ifstream instr("data/Box3_test2.txt");
	Box3 b(10, 20, 30, 40, 50, 60);
	instr >> b;
	instr.close();
	Box3 b1(1, 2, 3, 4, 5, 6);
	TEST_EQUAL(b, b1)
RESULT

NEW_TMP_FILE(filename)
CHECK(std::ostream& operator << (std::ostream& s, const TBox3<T>& Box3))
	Box3 v(1, 2, 3, 4, 5, 6);
	std::ofstream outstr(filename.c_str(), File::OUT);
	outstr << v;
	outstr.close();
	TEST_FILE(filename.c_str(), "data/Box3_test2.txt", false)
RESULT

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
END_TEST
<commit_msg>added: test rump for new methods (has, isIntersecting)<commit_after>// $Id: Box3_test.C,v 1.12 2000/09/05 09:59:13 oliver Exp $
#include <BALL/CONCEPT/classTest.h>

///////////////////////////
#	include <BALL/MATHS/box3.h>
#	include <BALL/MATHS/vector3.h>
///////////////////////////

START_TEST(class_name, "$Id: Box3_test.C,v 1.12 2000/09/05 09:59:13 oliver Exp $")

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

using namespace BALL;
using namespace std;

CHECK(TVector3::BALL_CREATE(TBox3<T>))
	Vector3 v1(1.0, 2.0, 3.0), v2(1.0, 2.0, 3.0);
	Vector3 v0;
	Box3 v(v1, v2);
	Box3* v_ptr = (Box3*)v.create(false, true);
	TEST_EQUAL(v_ptr->a == v0, true)
	TEST_EQUAL(v_ptr->b == v0, true)
	delete v_ptr;
	v_ptr = (Box3*)v.create();
	TEST_EQUAL(v_ptr->a == v1, true)
	TEST_EQUAL(v_ptr->b == v2, true)
	delete v_ptr;
RESULT

CHECK(TBox3::TBox3())
  Box3* box;
	box = new Box3();
	TEST_NOT_EQUAL(box, 0)
RESULT

Box3 box, box2;
Vector3 v1, v2, v3, v4;
float a = 1.0, b = 2.0, c = 3.0,
			d = 6.0, e = 5.0, f = 4.0;
float a1, b1, c1, d1, e1, f1;

v1 = Vector3(1.0, 2.0, 3.0);
v2 = Vector3(6.0, 5.0, 4.0);

String filename;
using std::ofstream;
using std::ios;

//also test for TBox3::get(T& ax, T& ay, T& az, T& bx, T& by, T& bz) const
CHECK(TBox3::TBox3(const T& ax, const T& ay, const T& az, const T& bx, const T& by, const T& bz))
	box = Box3(a, b, c, d, e, f);
	float a1, b1, c1, d1, e1, f1;
	box.get(a1, b1, c1, d1, e1, f1);
	TEST_REAL_EQUAL(a, a1)
	TEST_REAL_EQUAL(b, b1)
	TEST_REAL_EQUAL(c, c1)
	TEST_REAL_EQUAL(d, d1)
	TEST_REAL_EQUAL(e, e1)
	TEST_REAL_EQUAL(f, f1)
RESULT

CHECK(TBox3::TBox3(const TBox3<T>& box, bool /* deep */))
	box = Box3(v1, v2);
	box2 = Box3(box);
	float a1, b1, c1, d1, e1, f1;
	box2.get(a1, b1, c1, d1, e1, f1);
	TEST_REAL_EQUAL(a, a1)
	TEST_REAL_EQUAL(b, b1)
	TEST_REAL_EQUAL(c, c1)
	TEST_REAL_EQUAL(d, d1)
	TEST_REAL_EQUAL(e, e1)
	TEST_REAL_EQUAL(f, f1)
RESULT

CHECK(TBox3::TBox3(const TVector3<T>& a, const TVector3<T>& b))
	box = Box3(v1, v2);
	box.get(a1, b1, c1, d1, e1, f1);
	TEST_REAL_EQUAL(a, a1)
	TEST_REAL_EQUAL(b, b1)
	TEST_REAL_EQUAL(c, c1)
	TEST_REAL_EQUAL(d, d1)
	TEST_REAL_EQUAL(e, e1)
	TEST_REAL_EQUAL(f, f1)
RESULT

CHECK(TBox3::getSurface() const )
	box = Box3(v1, v2);
	TEST_REAL_EQUAL(box.getSurface(), 46.0)
RESULT

CHECK(TBox3::getVolume() const )
	box = Box3(v1, v2);
	TEST_REAL_EQUAL(box.getVolume(), 15.0)
RESULT

CHECK(TBox3::getWidth() const )
	box = Box3(v1, v2);
	TEST_REAL_EQUAL(box.getWidth(), 5.0)
RESULT

CHECK(TBox3::getHeight() const )
	box = Box3(v1, v2);
	TEST_REAL_EQUAL(box.getHeight(), 3.0)
RESULT

CHECK(TBox3::getDepth() const )
	box = Box3(v1, v2);
	TEST_REAL_EQUAL(box.getDepth(), 1.0)
RESULT

CHECK(TBox3::join(const TBox3& box))
	box = Box3(v1, v2);
	v3 = Vector3(101.0, 102.0, 103.0);
	v4 = Vector3(104.0, 105.0, 106.0);
	box2 = Box3(v3, v4);
	box.join(box2);
	box.get(a1, b1, c1, d1, e1, f1);
	TEST_REAL_EQUAL(1, a1)
	TEST_REAL_EQUAL(2, b1)
	TEST_REAL_EQUAL(3, c1)
	TEST_REAL_EQUAL(104, d1)
	TEST_REAL_EQUAL(105, e1)
	TEST_REAL_EQUAL(106, f1)
RESULT

CHECK(TBox3::bool operator == (const TBox3& box) const )
	box = Box3(v1, v2);
	box2 = Box3(v3, v4);
	TEST_EQUAL(box == box2, false)
	box2 = Box3(v1, v2);
	TEST_EQUAL(box == box2, true)
RESULT

CHECK(TBox3::bool operator != (const TBox3& box) const )
	box = Box3(v1, v2);
	box2 = Box3(v3, v4);
	TEST_EQUAL(box != box2, true)
	box2 = Box3(v1, v2);
	TEST_EQUAL(box != box2, false)
RESULT

CHECK(TBox3::isValid() const )
	box = Box3(v1, v2);
	TEST_EQUAL(box.isValid(), true)
RESULT

CHECK(bool TBox3::has(const TVector3<T>& point, bool on_surface = false) const)
	// BAUSTELLE
RESULT

CHECK(bool TBox3::isIntersecting(const TBox3& box) const)
	// BAUSTELLE
RESULT

CHECK(TBox3::set(const TBox3<T>& box, bool /* deep */))
	box = Box3(v1, v2);
	box2.set(box);
	TEST_EQUAL(box == box2, true)
RESULT

CHECK(TBox3::set(const T& ax, const T& ay, const T& az, const T& bx, const T& by, const T& bz))
	box = Box3(v1, v2);
	box2.set(1.0, 2.0, 3.0, 6.0, 5.0, 4.0);
	TEST_EQUAL(box == box2, true)
RESULT

CHECK(TBox3::get(TBox3<T>& box, bool deep) const )
	box = Box3(v1, v2);
	box.get(box2);
	TEST_EQUAL(box == box2, true)
RESULT

CHECK(TBox3::get(TVector3& lower, TVector3& upper) const)
	Box3 box;
	box2.get(box);
	TEST_EQUAL(box == box2, true)
RESULT

CHECK(TBox3::get(T& ax, T& ay, T& az, T& bx, T& by, T& bz) const )
	box = Box3(v1, v2);
	box.get(a1, b1, c1, d1, e1, f1);
	box2.set(a1, b1, c1, d1, e1, f1);
	TEST_EQUAL(box == box2, true)
RESULT

CHECK(TBox3::dump(std::ostream& s = std::cout, Size depth = 0) const )
	Box3 v(1.0, 2.0, 3.0, 4.0, 5.0, 6.0);
  String filename;
	NEW_TMP_FILE(filename)
	std::ofstream outfile(filename.c_str(), File::OUT);
	v.dump(outfile);
	outfile.close();
	TEST_FILE(filename.c_str(), "data/Box3_test.txt", true)
RESULT

CHECK(std::istream& operator >> (std::istream& s, TBox3<T>& Box3))
	std::ifstream instr("data/Box3_test2.txt");
	Box3 b(10, 20, 30, 40, 50, 60);
	instr >> b;
	instr.close();
	Box3 b1(1, 2, 3, 4, 5, 6);
	TEST_EQUAL(b, b1)
RESULT

NEW_TMP_FILE(filename)
CHECK(std::ostream& operator << (std::ostream& s, const TBox3<T>& Box3))
	Box3 v(1, 2, 3, 4, 5, 6);
	std::ofstream outstr(filename.c_str(), File::OUT);
	outstr << v;
	outstr.close();
	TEST_FILE(filename.c_str(), "data/Box3_test2.txt", false)
RESULT

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
END_TEST
<|endoftext|>


<commit_before><commit_msg>Quick fix<commit_after><|endoftext|>


<commit_before>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright 2011-2021 Dominik Charousset                                     *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#define CAF_SUITE response_promise

#include "caf/response_promise.hpp"

#include "core-test.hpp"

using namespace caf;

namespace {

behavior adder() {
  return {
    [](int x, int y) { return x + y; },
    [](ok_atom) {},
  };
}

behavior delegator(event_based_actor* self, actor worker) {
  return {
    [=](int x, int y) {
      auto promise = self->make_response_promise();
      return promise.delegate(worker, x, y);
    },
    [=](ok_atom) {
      auto promise = self->make_response_promise();
      return promise.delegate(worker, ok_atom_v);
    },
  };
}

behavior requester_v1(event_based_actor* self, actor worker) {
  return {
    [=](int x, int y) {
      auto rp = self->make_response_promise();
      self->request(worker, infinite, x, y)
        .then(
          [rp](int result) mutable {
            CHECK(rp.pending());
            rp.deliver(result);
          },
          [rp](error err) mutable {
            CHECK(rp.pending());
            rp.deliver(std::move(err));
          });
      return rp;
    },
    [=](ok_atom) {
      auto rp = self->make_response_promise();
      self->request(worker, infinite, ok_atom_v)
        .then(
          [rp]() mutable {
            CHECK(rp.pending());
            rp.deliver();
          },
          [rp](error err) mutable {
            CHECK(rp.pending());
            rp.deliver(std::move(err));
          });
      return rp;
    },
  };
}

behavior requester_v2(event_based_actor* self, actor worker) {
  return {
    [=](int x, int y) {
      auto rp = self->make_response_promise();
      auto deliver = [rp](expected<int> x) mutable {
        CHECK(rp.pending());
        rp.deliver(std::move(x));
      };
      self->request(worker, infinite, x, y)
        .then([deliver](int result) mutable { deliver(result); },
              [deliver](error err) mutable { deliver(std::move(err)); });
      return rp;
    },
    [=](ok_atom) {
      auto rp = self->make_response_promise();
      auto deliver = [rp](expected<void> x) mutable {
        CHECK(rp.pending());
        rp.deliver(std::move(x));
      };
      self->request(worker, infinite, ok_atom_v)
        .then([deliver]() mutable { deliver({}); },
              [deliver](error err) mutable { deliver(std::move(err)); });
      return rp;
    },
  };
}

} // namespace

CAF_TEST_FIXTURE_SCOPE(response_promise_tests, test_coordinator_fixture<>)

SCENARIO("response promises allow delaying of response messages") {
  auto adder_hdl = sys.spawn(adder);
  std::map<std::string, actor> impls;
  impls["with a value or an error"] = sys.spawn(requester_v1, adder_hdl);
  impls["with an expected<T>"] = sys.spawn(requester_v2, adder_hdl);
  for (auto& [desc, hdl] : impls) {
    GIVEN("a dispatcher that calls deliver " << desc << " on its promise") {
      WHEN("sending a request with two integers to the dispatcher") {
        inject((int, int), from(self).to(hdl).with(3, 4));
        THEN("clients receive the response from the dispatcher") {
          expect((int, int), from(hdl).to(adder_hdl).with(3, 4));
          expect((int), from(adder_hdl).to(hdl).with(7));
          expect((int), from(hdl).to(self).with(7));
        }
      }
      WHEN("sending ok_atom to the dispatcher synchronously") {
        auto res = self->request(hdl, infinite, ok_atom_v);
        auto fetch_result = [&] {
          message result;
          res.receive([] {}, // void result
                      [&](const error& reason) {
                        result = make_message(reason);
                      });
          return result;
        };
        THEN("clients receive an empty response from the dispatcher") {
          expect((ok_atom), from(self).to(hdl));
          expect((ok_atom), from(hdl).to(adder_hdl));
          expect((void), from(adder_hdl).to(hdl));
          CHECK(fetch_result().empty());
        }
      }
      WHEN("sending ok_atom to the dispatcher asynchronously") {
        THEN("clients receive no response from the dispatcher") {
          inject((ok_atom), from(self).to(hdl).with(ok_atom_v));
          expect((ok_atom), from(hdl).to(adder_hdl));
          expect((void), from(adder_hdl).to(hdl));
          CHECK(self->mailbox().empty());
        }
      }
    }
  }
}

SCENARIO("response promises allow delegation") {
  GIVEN("a dispatcher that calls delegate on its promise") {
    auto adder_hdl = sys.spawn(adder);
    auto hdl = sys.spawn(delegator, adder_hdl);
    WHEN("sending a request to the dispatcher") {
      inject((int, int), from(self).to(hdl).with(3, 4));
      THEN("clients receive the response from the adder") {
        expect((int, int), from(self).to(adder_hdl).with(3, 4));
        expect((int), from(adder_hdl).to(self).with(7));
      }
    }
  }
}

CAF_TEST_FIXTURE_SCOPE_END()
<commit_msg>Fix handling of expected<T> in response promises<commit_after>// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.

#define CAF_SUITE response_promise

#include "caf/response_promise.hpp"

#include "core-test.hpp"

using namespace caf;

namespace {

behavior adder() {
  return {
    [](int x, int y) { return x + y; },
    [](ok_atom) {},
  };
}

behavior delegator(event_based_actor* self, actor worker) {
  return {
    [=](int x, int y) {
      auto promise = self->make_response_promise();
      return promise.delegate(worker, x, y);
    },
    [=](ok_atom) {
      auto promise = self->make_response_promise();
      return promise.delegate(worker, ok_atom_v);
    },
  };
}

behavior requester_v1(event_based_actor* self, actor worker) {
  return {
    [=](int x, int y) {
      auto rp = self->make_response_promise();
      self->request(worker, infinite, x, y)
        .then(
          [rp](int result) mutable {
            CHECK(rp.pending());
            rp.deliver(result);
          },
          [rp](error err) mutable {
            CHECK(rp.pending());
            rp.deliver(std::move(err));
          });
      return rp;
    },
    [=](ok_atom) {
      auto rp = self->make_response_promise();
      self->request(worker, infinite, ok_atom_v)
        .then(
          [rp]() mutable {
            CHECK(rp.pending());
            rp.deliver();
          },
          [rp](error err) mutable {
            CHECK(rp.pending());
            rp.deliver(std::move(err));
          });
      return rp;
    },
  };
}

behavior requester_v2(event_based_actor* self, actor worker) {
  return {
    [=](int x, int y) {
      auto rp = self->make_response_promise();
      auto deliver = [rp](expected<int> x) mutable {
        CHECK(rp.pending());
        rp.deliver(std::move(x));
      };
      self->request(worker, infinite, x, y)
        .then([deliver](int result) mutable { deliver(result); },
              [deliver](error err) mutable { deliver(std::move(err)); });
      return rp;
    },
    [=](ok_atom) {
      auto rp = self->make_response_promise();
      auto deliver = [rp](expected<void> x) mutable {
        CHECK(rp.pending());
        rp.deliver(std::move(x));
      };
      self->request(worker, infinite, ok_atom_v)
        .then([deliver]() mutable { deliver({}); },
              [deliver](error err) mutable { deliver(std::move(err)); });
      return rp;
    },
  };
}

} // namespace

CAF_TEST_FIXTURE_SCOPE(response_promise_tests, test_coordinator_fixture<>)

SCENARIO("response promises allow delaying of response messages") {
  auto adder_hdl = sys.spawn(adder);
  std::map<std::string, actor> impls;
  impls["with a value or an error"] = sys.spawn(requester_v1, adder_hdl);
  impls["with an expected<T>"] = sys.spawn(requester_v2, adder_hdl);
  for (auto& [desc, hdl] : impls) {
    GIVEN("a dispatcher that calls deliver " << desc << " on its promise") {
      WHEN("sending a request with two integers to the dispatcher") {
        inject((int, int), from(self).to(hdl).with(3, 4));
        THEN("clients receive the response from the dispatcher") {
          expect((int, int), from(hdl).to(adder_hdl).with(3, 4));
          expect((int), from(adder_hdl).to(hdl).with(7));
          expect((int), from(hdl).to(self).with(7));
        }
      }
      WHEN("sending ok_atom to the dispatcher synchronously") {
        auto res = self->request(hdl, infinite, ok_atom_v);
        auto fetch_result = [&] {
          message result;
          res.receive([] {}, // void result
                      [&](const error& reason) {
                        result = make_message(reason);
                      });
          return result;
        };
        THEN("clients receive an empty response from the dispatcher") {
          expect((ok_atom), from(self).to(hdl));
          expect((ok_atom), from(hdl).to(adder_hdl));
          expect((void), from(adder_hdl).to(hdl));
          CHECK(fetch_result().empty());
        }
      }
      WHEN("sending ok_atom to the dispatcher asynchronously") {
        THEN("clients receive no response from the dispatcher") {
          inject((ok_atom), from(self).to(hdl).with(ok_atom_v));
          expect((ok_atom), from(hdl).to(adder_hdl));
          expect((void), from(adder_hdl).to(hdl));
          CHECK(self->mailbox().empty());
        }
      }
    }
  }
}

SCENARIO("response promises allow delegation") {
  GIVEN("a dispatcher that calls delegate on its promise") {
    auto adder_hdl = sys.spawn(adder);
    auto hdl = sys.spawn(delegator, adder_hdl);
    WHEN("sending a request to the dispatcher") {
      inject((int, int), from(self).to(hdl).with(3, 4));
      THEN("clients receive the response from the adder") {
        expect((int, int), from(self).to(adder_hdl).with(3, 4));
        expect((int), from(adder_hdl).to(self).with(7));
      }
    }
  }
}

CAF_TEST_FIXTURE_SCOPE_END()
<|endoftext|>


<commit_before><commit_msg>Fix crash on unhooking function when capture_data is not available<commit_after><|endoftext|>


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

#include "boost/bind.hpp"

#include "IECore/SharedSceneInterfaces.h"
#include "IECore/InternedString.h"
#include "IECore/SceneCache.h"

#include "Gaffer/Context.h"

#include "GafferScene/SceneReader.h"

using namespace std;
using namespace Imath;
using namespace IECore;
using namespace Gaffer;
using namespace GafferScene;

IE_CORE_DEFINERUNTIMETYPED( SceneReader );

//////////////////////////////////////////////////////////////////////////
// SceneReader implementation
//////////////////////////////////////////////////////////////////////////

/// \todo hard coded framerate should be replaced with a getTime() method on Gaffer::Context or something
const double SceneReader::g_frameRate( 24 );
size_t SceneReader::g_firstPlugIndex = 0;

static IECore::BoolDataPtr g_trueBoolData = new IECore::BoolData( true );

SceneReader::SceneReader( const std::string &name )
	:	FileSource( name )
{
	storeIndexOfNextChild( g_firstPlugIndex );
	addChild( new StringPlug( "tags" ) );
	plugSetSignal().connect( boost::bind( &SceneReader::plugSet, this, ::_1 ) );
}

SceneReader::~SceneReader()
{
}

Gaffer::StringPlug *SceneReader::tagsPlug()
{
	return getChild<StringPlug>( g_firstPlugIndex );
}

const Gaffer::StringPlug *SceneReader::tagsPlug() const
{
	return getChild<StringPlug>( g_firstPlugIndex );
}

void SceneReader::affects( const Gaffer::Plug *input, AffectedPlugsContainer &outputs ) const
{
	FileSource::affects( input, outputs );

	if( input == tagsPlug() )
	{
		outputs.push_back( outPlug()->childNamesPlug() );
	}
}

size_t SceneReader::supportedExtensions( std::vector<std::string> &extensions )
{
	extensions = SceneInterface::supportedExtensions();
	return extensions.size();
}

void SceneReader::hashBound( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const
{
	FileSource::hashBound( path, context, parent, h );

	ConstSceneInterfacePtr s = scene( path );
	const SampledSceneInterface *ss = runTimeCast<const SampledSceneInterface>( s.get() );
	if( !ss || ss->numBoundSamples() > 1 )
	{
		h.append( context->getFrame() );
	}
}

void SceneReader::hashTransform( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const
{
	FileSource::hashTransform( path, context, parent, h );

	ConstSceneInterfacePtr s = scene( path );
	if( !s )
	{
		return;
	}

	const SampledSceneInterface *ss = runTimeCast<const SampledSceneInterface>( s.get() );
	if( !ss || ss->numTransformSamples() > 1 )
	{
		h.append( context->getFrame() );
	}
}

void SceneReader::hashAttributes( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const
{
	ConstSceneInterfacePtr s = scene( path );
	if( !s )
	{
		h = parent->attributesPlug()->defaultValue()->Object::hash();
		return;
	}

	SceneInterface::NameList attributeNames;
	s->attributeNames( attributeNames );
	SceneInterface::NameList tagNames;
	s->readTags( tagNames, IECore::SceneInterface::LocalTag );

	if( !attributeNames.size() && !tagNames.size() )
	{
		h = parent->attributesPlug()->defaultValue()->Object::hash();
		return;
	}

	FileSource::hashAttributes( path, context, parent, h );

	bool animated = false;
	const SampledSceneInterface *ss = runTimeCast<const SampledSceneInterface>( s.get() );
	if( !ss )
	{
		animated = true;
	}
	else
	{
		for( SceneInterface::NameList::iterator it = attributeNames.begin(); it != attributeNames.end(); ++it )
		{
			if( ss->numAttributeSamples( *it ) > 1 )
			{
				animated = true;
				break;
			}
		}
	}

	if( animated )
	{
		h.append( context->getFrame() );
	}
}

void SceneReader::hashObject( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const
{
	ConstSceneInterfacePtr s = scene( path );
	if( !s || !s->hasObject() )
	{
		// no object
		h = parent->objectPlug()->defaultValue()->hash();
		return;
	}

	FileSource::hashObject( path, context, parent, h );
	const SampledSceneInterface *ss = runTimeCast<const SampledSceneInterface>( s.get() );
	if( !ss || ss->numObjectSamples() > 1 )
	{
		h.append( context->getFrame() );
	}
}

void SceneReader::hashChildNames( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const
{
	FileSource::hashChildNames( path, context, parent, h );
	tagsPlug()->hash( h );
}

Imath::Box3f SceneReader::computeBound( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	ConstSceneInterfacePtr s = scene( path );
	if( !s )
	{
		return Box3f();
	}

	Box3d b = s->readBound( context->getFrame() / g_frameRate );

	if( b.isEmpty() )
	{
		return Box3f();
	}

	return Box3f( b.min, b.max );
}

Imath::M44f SceneReader::computeTransform( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	ConstSceneInterfacePtr s = scene( path );
	if( !s )
	{
		return M44f();
	}

	M44d t = s->readTransformAsMatrix( context->getFrame() / g_frameRate );

	return M44f(
		t[0][0], t[0][1], t[0][2], t[0][3],
		t[1][0], t[1][1], t[1][2], t[1][3],
		t[2][0], t[2][1], t[2][2], t[2][3],
		t[3][0], t[3][1], t[3][2], t[3][3]
	);
}

IECore::ConstCompoundObjectPtr SceneReader::computeAttributes( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	ConstSceneInterfacePtr s = scene( path );
	if( !s )
	{
		return parent->attributesPlug()->defaultValue();
	}

	// read attributes

	SceneInterface::NameList nameList;
	s->attributeNames( nameList );

	CompoundObjectPtr result = new CompoundObject;

	for( SceneInterface::NameList::iterator it = nameList.begin(); it != nameList.end(); ++it )
	{
		// these internal attributes should be ignored:
		if( *it == SceneCache::animatedObjectTopologyAttribute )
		{
			continue;
		}
		if( *it == SceneCache::animatedObjectPrimVarsAttribute )
		{
			continue;
		}

		// the const cast is ok, because we're only using it to put the object into a CompoundObject that will
		// be treated as forever const after being returned from this function.
		result->members()[ std::string( *it ) ] = constPointerCast<Object>( s->readAttribute( *it, context->getFrame() / g_frameRate ) );
	}

	// read tags and turn them into attributes of the form "user:tag:tagName"

	nameList.clear();
	s->readTags( nameList, IECore::SceneInterface::LocalTag );
	for( SceneInterface::NameList::const_iterator it = nameList.begin(); it != nameList.end(); ++it )
	{
		if( it->string().compare( 0, 11, "ObjectType:" ) == 0 )
		{
			continue;
		}
		result->members()["user:tag:"+it->string()] = g_trueBoolData;
	}

	return result;
}

IECore::ConstObjectPtr SceneReader::computeObject( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	ConstSceneInterfacePtr s = scene( path );
	if( !s || !s->hasObject() )
	{
		return parent->objectPlug()->defaultValue();
	}

	return s->readObject( context->getFrame() / g_frameRate );
}

IECore::ConstInternedStringVectorDataPtr SceneReader::computeChildNames( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	ConstSceneInterfacePtr s = scene( path );
	if( !s )
	{
		return parent->childNamesPlug()->defaultValue();
	}

	// get the child names

	InternedStringVectorDataPtr resultData = new InternedStringVectorData;
	vector<InternedString> &result = resultData->writable();
	s->childNames( result );

	// filter out any which don't have the right tags

	std::string tagsString = tagsPlug()->getValue();
	if( !tagsString.empty() )
	{
		typedef boost::tokenizer<boost::char_separator<char> > Tokenizer;
		Tokenizer tagsTokenizer( tagsString, boost::char_separator<char>( " " ) );

		vector<InternedString> tags;
		std::copy( tagsTokenizer.begin(), tagsTokenizer.end(), back_inserter( tags ) );

		vector<InternedString>::iterator newResultEnd = result.begin();
		SceneInterface::NameList childTags;
		for( vector<InternedString>::const_iterator cIt = result.begin(), cEIt = result.end(); cIt != cEIt; ++cIt )
		{
			ConstSceneInterfacePtr child = s->child( *cIt );
			childTags.clear();
			child->readTags( childTags, IECore::SceneInterface::EveryTag );

			bool childMatches = false;
			for( SceneInterface::NameList::const_iterator tIt = childTags.begin(), tEIt = childTags.end(); tIt != tEIt; ++tIt )
			{
				if( find( tags.begin(), tags.end(), *tIt ) != tags.end() )
				{
					childMatches = true;
					break;
				}
			}

			if( childMatches )
			{
				*newResultEnd++ = *cIt;
			}
		}

		result.erase( newResultEnd, result.end() );
	}

	return resultData;
}

IECore::ConstCompoundObjectPtr SceneReader::computeGlobals( const Gaffer::Context *context, const ScenePlug *parent ) const
{
	return parent->globalsPlug()->defaultValue();
}

void SceneReader::plugSet( Gaffer::Plug *plug )
{
	// this clears the cache every time the refresh count is updated, so you don't get entries
	// from old files hanging around and screwing up the hierarchy.
	/// \todo The fact that this clears the cache for all nodes, ever is a problem - find a better
	// way of doing this!
	if( plug == refreshCountPlug() )
	{
		SharedSceneInterfaces::clear();
		m_lastScene.clear();
	}
}

ConstSceneInterfacePtr SceneReader::scene( const ScenePath &path ) const
{
	std::string fileName = fileNamePlug()->getValue();
	if( !fileName.size() )
	{
		return NULL;
	}

	LastScene &lastScene = m_lastScene.local();
	if( lastScene.fileName == fileName )
	{
		if( lastScene.path == path )
		{
			return lastScene.pathScene;
		}
		else
		{
			lastScene.path = path;
			lastScene.pathScene = lastScene.fileNameScene->scene( path );
			return lastScene.pathScene;
		}
	}

	lastScene.fileName = fileName;
	lastScene.fileNameScene = SharedSceneInterfaces::get( fileName );
	lastScene.path = path;
	lastScene.pathScene = lastScene.fileNameScene->scene( path );
	return lastScene.pathScene;
}
<commit_msg>Interleaved hash/compute methods in SceneReader.cpp.<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2013-2014, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//      * Redistributions of source code must retain the above
//        copyright notice, this list of conditions and the following
//        disclaimer.
//
//      * Redistributions in binary form must reproduce the above
//        copyright notice, this list of conditions and the following
//        disclaimer in the documentation and/or other materials provided with
//        the distribution.
//
//      * Neither the name of John Haddon nor the names of
//        any other contributors to this software may be used to endorse or
//        promote products derived from this software without specific prior
//        written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "boost/bind.hpp"

#include "IECore/SharedSceneInterfaces.h"
#include "IECore/InternedString.h"
#include "IECore/SceneCache.h"

#include "Gaffer/Context.h"

#include "GafferScene/SceneReader.h"

using namespace std;
using namespace Imath;
using namespace IECore;
using namespace Gaffer;
using namespace GafferScene;

IE_CORE_DEFINERUNTIMETYPED( SceneReader );

//////////////////////////////////////////////////////////////////////////
// SceneReader implementation
//////////////////////////////////////////////////////////////////////////

/// \todo hard coded framerate should be replaced with a getTime() method on Gaffer::Context or something
const double SceneReader::g_frameRate( 24 );
size_t SceneReader::g_firstPlugIndex = 0;

static IECore::BoolDataPtr g_trueBoolData = new IECore::BoolData( true );

SceneReader::SceneReader( const std::string &name )
	:	FileSource( name )
{
	storeIndexOfNextChild( g_firstPlugIndex );
	addChild( new StringPlug( "tags" ) );
	plugSetSignal().connect( boost::bind( &SceneReader::plugSet, this, ::_1 ) );
}

SceneReader::~SceneReader()
{
}

Gaffer::StringPlug *SceneReader::tagsPlug()
{
	return getChild<StringPlug>( g_firstPlugIndex );
}

const Gaffer::StringPlug *SceneReader::tagsPlug() const
{
	return getChild<StringPlug>( g_firstPlugIndex );
}

void SceneReader::affects( const Gaffer::Plug *input, AffectedPlugsContainer &outputs ) const
{
	FileSource::affects( input, outputs );

	if( input == tagsPlug() )
	{
		outputs.push_back( outPlug()->childNamesPlug() );
	}
}

size_t SceneReader::supportedExtensions( std::vector<std::string> &extensions )
{
	extensions = SceneInterface::supportedExtensions();
	return extensions.size();
}

void SceneReader::hashBound( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const
{
	FileSource::hashBound( path, context, parent, h );

	ConstSceneInterfacePtr s = scene( path );
	const SampledSceneInterface *ss = runTimeCast<const SampledSceneInterface>( s.get() );
	if( !ss || ss->numBoundSamples() > 1 )
	{
		h.append( context->getFrame() );
	}
}

Imath::Box3f SceneReader::computeBound( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	ConstSceneInterfacePtr s = scene( path );
	if( !s )
	{
		return Box3f();
	}

	Box3d b = s->readBound( context->getFrame() / g_frameRate );

	if( b.isEmpty() )
	{
		return Box3f();
	}

	return Box3f( b.min, b.max );
}

void SceneReader::hashTransform( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const
{
	FileSource::hashTransform( path, context, parent, h );

	ConstSceneInterfacePtr s = scene( path );
	if( !s )
	{
		return;
	}

	const SampledSceneInterface *ss = runTimeCast<const SampledSceneInterface>( s.get() );
	if( !ss || ss->numTransformSamples() > 1 )
	{
		h.append( context->getFrame() );
	}
}

Imath::M44f SceneReader::computeTransform( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	ConstSceneInterfacePtr s = scene( path );
	if( !s )
	{
		return M44f();
	}

	M44d t = s->readTransformAsMatrix( context->getFrame() / g_frameRate );

	return M44f(
		t[0][0], t[0][1], t[0][2], t[0][3],
		t[1][0], t[1][1], t[1][2], t[1][3],
		t[2][0], t[2][1], t[2][2], t[2][3],
		t[3][0], t[3][1], t[3][2], t[3][3]
	);
}

void SceneReader::hashAttributes( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const
{
	ConstSceneInterfacePtr s = scene( path );
	if( !s )
	{
		h = parent->attributesPlug()->defaultValue()->Object::hash();
		return;
	}

	SceneInterface::NameList attributeNames;
	s->attributeNames( attributeNames );
	SceneInterface::NameList tagNames;
	s->readTags( tagNames, IECore::SceneInterface::LocalTag );

	if( !attributeNames.size() && !tagNames.size() )
	{
		h = parent->attributesPlug()->defaultValue()->Object::hash();
		return;
	}

	FileSource::hashAttributes( path, context, parent, h );

	bool animated = false;
	const SampledSceneInterface *ss = runTimeCast<const SampledSceneInterface>( s.get() );
	if( !ss )
	{
		animated = true;
	}
	else
	{
		for( SceneInterface::NameList::iterator it = attributeNames.begin(); it != attributeNames.end(); ++it )
		{
			if( ss->numAttributeSamples( *it ) > 1 )
			{
				animated = true;
				break;
			}
		}
	}

	if( animated )
	{
		h.append( context->getFrame() );
	}
}

IECore::ConstCompoundObjectPtr SceneReader::computeAttributes( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	ConstSceneInterfacePtr s = scene( path );
	if( !s )
	{
		return parent->attributesPlug()->defaultValue();
	}

	// read attributes

	SceneInterface::NameList nameList;
	s->attributeNames( nameList );

	CompoundObjectPtr result = new CompoundObject;

	for( SceneInterface::NameList::iterator it = nameList.begin(); it != nameList.end(); ++it )
	{
		// these internal attributes should be ignored:
		if( *it == SceneCache::animatedObjectTopologyAttribute )
		{
			continue;
		}
		if( *it == SceneCache::animatedObjectPrimVarsAttribute )
		{
			continue;
		}

		// the const cast is ok, because we're only using it to put the object into a CompoundObject that will
		// be treated as forever const after being returned from this function.
		result->members()[ std::string( *it ) ] = constPointerCast<Object>( s->readAttribute( *it, context->getFrame() / g_frameRate ) );
	}

	// read tags and turn them into attributes of the form "user:tag:tagName"

	nameList.clear();
	s->readTags( nameList, IECore::SceneInterface::LocalTag );
	for( SceneInterface::NameList::const_iterator it = nameList.begin(); it != nameList.end(); ++it )
	{
		if( it->string().compare( 0, 11, "ObjectType:" ) == 0 )
		{
			continue;
		}
		result->members()["user:tag:"+it->string()] = g_trueBoolData;
	}

	return result;
}

void SceneReader::hashObject( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const
{
	ConstSceneInterfacePtr s = scene( path );
	if( !s || !s->hasObject() )
	{
		// no object
		h = parent->objectPlug()->defaultValue()->hash();
		return;
	}

	FileSource::hashObject( path, context, parent, h );
	const SampledSceneInterface *ss = runTimeCast<const SampledSceneInterface>( s.get() );
	if( !ss || ss->numObjectSamples() > 1 )
	{
		h.append( context->getFrame() );
	}
}

IECore::ConstObjectPtr SceneReader::computeObject( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	ConstSceneInterfacePtr s = scene( path );
	if( !s || !s->hasObject() )
	{
		return parent->objectPlug()->defaultValue();
	}

	return s->readObject( context->getFrame() / g_frameRate );
}

void SceneReader::hashChildNames( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const
{
	FileSource::hashChildNames( path, context, parent, h );
	tagsPlug()->hash( h );
}

IECore::ConstInternedStringVectorDataPtr SceneReader::computeChildNames( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	ConstSceneInterfacePtr s = scene( path );
	if( !s )
	{
		return parent->childNamesPlug()->defaultValue();
	}

	// get the child names

	InternedStringVectorDataPtr resultData = new InternedStringVectorData;
	vector<InternedString> &result = resultData->writable();
	s->childNames( result );

	// filter out any which don't have the right tags

	std::string tagsString = tagsPlug()->getValue();
	if( !tagsString.empty() )
	{
		typedef boost::tokenizer<boost::char_separator<char> > Tokenizer;
		Tokenizer tagsTokenizer( tagsString, boost::char_separator<char>( " " ) );

		vector<InternedString> tags;
		std::copy( tagsTokenizer.begin(), tagsTokenizer.end(), back_inserter( tags ) );

		vector<InternedString>::iterator newResultEnd = result.begin();
		SceneInterface::NameList childTags;
		for( vector<InternedString>::const_iterator cIt = result.begin(), cEIt = result.end(); cIt != cEIt; ++cIt )
		{
			ConstSceneInterfacePtr child = s->child( *cIt );
			childTags.clear();
			child->readTags( childTags, IECore::SceneInterface::EveryTag );

			bool childMatches = false;
			for( SceneInterface::NameList::const_iterator tIt = childTags.begin(), tEIt = childTags.end(); tIt != tEIt; ++tIt )
			{
				if( find( tags.begin(), tags.end(), *tIt ) != tags.end() )
				{
					childMatches = true;
					break;
				}
			}

			if( childMatches )
			{
				*newResultEnd++ = *cIt;
			}
		}

		result.erase( newResultEnd, result.end() );
	}

	return resultData;
}

IECore::ConstCompoundObjectPtr SceneReader::computeGlobals( const Gaffer::Context *context, const ScenePlug *parent ) const
{
	return parent->globalsPlug()->defaultValue();
}

void SceneReader::plugSet( Gaffer::Plug *plug )
{
	// this clears the cache every time the refresh count is updated, so you don't get entries
	// from old files hanging around and screwing up the hierarchy.
	/// \todo The fact that this clears the cache for all nodes, ever is a problem - find a better
	// way of doing this!
	if( plug == refreshCountPlug() )
	{
		SharedSceneInterfaces::clear();
		m_lastScene.clear();
	}
}

ConstSceneInterfacePtr SceneReader::scene( const ScenePath &path ) const
{
	std::string fileName = fileNamePlug()->getValue();
	if( !fileName.size() )
	{
		return NULL;
	}

	LastScene &lastScene = m_lastScene.local();
	if( lastScene.fileName == fileName )
	{
		if( lastScene.path == path )
		{
			return lastScene.pathScene;
		}
		else
		{
			lastScene.path = path;
			lastScene.pathScene = lastScene.fileNameScene->scene( path );
			return lastScene.pathScene;
		}
	}

	lastScene.fileName = fileName;
	lastScene.fileNameScene = SharedSceneInterfaces::get( fileName );
	lastScene.path = path;
	lastScene.pathScene = lastScene.fileNameScene->scene( path );
	return lastScene.pathScene;
}
<|endoftext|>


<commit_before>// ---------------------------------------------------------------------
//
// Copyright (C) 1998 - 2015 by the deal.II authors
//
// This file is part of the deal.II library.
//
// The deal.II library is free software; you can use it, redistribute
// it, and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// The full text of the license can be found in the file LICENSE at
// the top level of the deal.II distribution.
//
// ---------------------------------------------------------------------

#include <deal.II/base/tensor.h>
#include <deal.II/grid/manifold.h>
#include <deal.II/grid/tria.h>
#include <deal.II/grid/tria_iterator.h>
#include <deal.II/grid/tria_accessor.h>
#include <deal.II/fe/fe_q.h>
#include <cmath>

DEAL_II_NAMESPACE_OPEN

using namespace Manifolds;

/* -------------------------- Manifold --------------------- */

template <int dim, int spacedim>
Manifold<dim, spacedim>::~Manifold ()
{}

template <int dim, int spacedim>
Point<spacedim>
Manifold<dim, spacedim>::
project_to_manifold (const std::vector<Point<spacedim> > &,
                     const Point<spacedim> &) const
{
  Assert (false, ExcPureFunctionCalled());
  return Point<spacedim>();
}

template <int dim, int spacedim>
Point<spacedim>
Manifold<dim, spacedim>::
get_new_point (const Quadrature<spacedim> &quad) const
{
  Assert(std::abs(std::accumulate(quad.get_weights().begin(), quad.get_weights().end(), 0.0)-1.0) < 1e-10,
         ExcMessage("The weights for the individual points should sum to 1!"));

  Point<spacedim> p;
  for (unsigned int i=0; i<quad.size(); ++i)
    p += quad.weight(i) * quad.point(i);

  return project_to_manifold(quad.get_points(), p);
}

template <int dim, int spacedim>
Point<spacedim>
Manifold<dim, spacedim>::
get_new_point_on_line (const typename Triangulation<dim, spacedim>::line_iterator &line) const
{
  return get_new_point (get_default_quadrature(line));
}

template <int dim, int spacedim>
Point<spacedim>
Manifold<dim, spacedim>::
get_new_point_on_quad (const typename Triangulation<dim, spacedim>::quad_iterator &quad) const
{
  return get_new_point (get_default_quadrature(quad));
}

template <int dim, int spacedim>
Point<spacedim>
Manifold<dim,spacedim>::
get_new_point_on_face (const typename Triangulation<dim,spacedim>::face_iterator &face) const
{
  Assert (dim>1, ExcImpossibleInDim(dim));

  switch (dim)
    {
    case 2:
      return get_new_point_on_line (face);
    case 3:
      return get_new_point_on_quad (face);
    }

  return Point<spacedim>();
}

template <int dim, int spacedim>
Point<spacedim>
Manifold<dim,spacedim>::
get_new_point_on_cell (const typename Triangulation<dim,spacedim>::cell_iterator &cell) const
{
  switch (dim)
    {
    case 1:
      return get_new_point_on_line (cell);
    case 2:
      return get_new_point_on_quad (cell);
    case 3:
      return get_new_point_on_hex (cell);
    }

  return Point<spacedim>();
}

template <>
Point<1>
Manifold<1,1>::
get_new_point_on_face (const Triangulation<1,1>::face_iterator &) const
{
  Assert (false, ExcImpossibleInDim(1));
  return Point<1>();
}

template <>
Point<2>
Manifold<1,2>::
get_new_point_on_face (const Triangulation<1,2>::face_iterator &) const
{
  Assert (false, ExcImpossibleInDim(1));
  return Point<2>();
}

template <>
Point<3>
Manifold<1,3>::
get_new_point_on_face (const Triangulation<1,3>::face_iterator &) const
{
  Assert (false, ExcImpossibleInDim(1));
  return Point<3>();
}

template <>
Point<1>
Manifold<1,1>::
get_new_point_on_quad (const Triangulation<1,1>::quad_iterator &) const
{
  Assert (false, ExcImpossibleInDim(1));
  return Point<1>();
}

template <>
Point<2>
Manifold<1,2>::
get_new_point_on_quad (const Triangulation<1,2>::quad_iterator &) const
{
  Assert (false, ExcImpossibleInDim(1));
  return Point<2>();
}

template <>
Point<3>
Manifold<1,3>::
get_new_point_on_quad (const Triangulation<1,3>::quad_iterator &) const
{
  Assert (false, ExcImpossibleInDim(1));
  return Point<3>();
}

template <int dim, int spacedim>
Point<spacedim>
Manifold<dim, spacedim>::
get_new_point_on_hex (const typename Triangulation<dim, spacedim>::hex_iterator &/*hex*/) const
{
  Assert (false, ExcImpossibleInDim(dim));
  return Point<spacedim>();
}

template <>
Point<3>
Manifold<3,3>::
get_new_point_on_hex (const Triangulation<3, 3>::hex_iterator &hex) const
{
  return get_new_point(get_default_quadrature(hex, true));
}

template <int dim, int spacedim>
Tensor<1,spacedim>
Manifold<dim,spacedim>::get_tangent_vector(const Point<spacedim> &x1,
                                           const Point<spacedim> &x2) const
{
  const double epsilon = 1e-8;

  std::vector<Point<spacedim> > q;
  q.push_back(x1);
  q.push_back(x2);

  std::vector<double> w;
  w.push_back(epsilon);
  w.push_back(1.0-epsilon);

  const Tensor<1,spacedim> neighbor_point = get_new_point (Quadrature<spacedim>(q, w));
  return (neighbor_point-x1)/epsilon;
}

/* -------------------------- FlatManifold --------------------- */

template <int dim, int spacedim>
FlatManifold<dim,spacedim>::FlatManifold (const Point<spacedim> periodicity,
                                          const double tolerance) :
  periodicity(periodicity),
  tolerance(tolerance)
{}

template <int dim, int spacedim>
Point<spacedim>
FlatManifold<dim, spacedim>::
get_new_point (const Quadrature<spacedim> &quad) const
{
  Assert(std::abs(std::accumulate(quad.get_weights().begin(), quad.get_weights().end(), 0.0)-1.0) < 1e-10,
         ExcMessage("The weights for the individual points should sum to 1!"));

  const std::vector<Point<spacedim> > &surrounding_points = quad.get_points();
  const std::vector<double> &weights = quad.get_weights();

  Point<spacedim> p;
  Point<spacedim> dp;
  Point<spacedim> minP = periodicity;
  const bool check_period = (periodicity.norm() > tolerance);
  if (check_period)
    for (unsigned int i=0; i<surrounding_points.size(); ++i)
      for (unsigned int d=0; d<spacedim; ++d)
        {
          minP[d] = std::min(minP[d], surrounding_points[i][d]);
          if (periodicity[d] > 0)
            Assert( (surrounding_points[i][d] < periodicity[d]+tolerance*periodicity.norm()) ||
                    (surrounding_points[i][d] >= -tolerance*periodicity.norm()),
                    ExcPeriodicBox(d, surrounding_points[i], periodicity, tolerance*periodicity.norm()));
        }

  for (unsigned int i=0; i<surrounding_points.size(); ++i)
    {
      dp = Point<spacedim>();
      if (check_period)
        {
          for (unsigned int d=0; d<spacedim; ++d)
            if (periodicity[d] > 0)
              dp[d] = ( (surrounding_points[i][d]-minP[d]) > periodicity[d]/2.0 ?
                        -periodicity[d] : 0.0 );
        }
      p += (surrounding_points[i]+dp)*weights[i];
    }
  if (check_period)
    for (unsigned int d=0; d<spacedim; ++d)
      if (periodicity[d] > 0)
        p[d] = (p[d] < 0 ? p[d] + periodicity[d] : p[d]);

  return project_to_manifold(surrounding_points, p);
}

template <int dim, int spacedim>
Point<spacedim>
FlatManifold<dim, spacedim>::project_to_manifold (const std::vector<Point<spacedim> > &/*vertices*/,
                                                  const Point<spacedim> &candidate) const
{
  return candidate;
}

template <int dim, int spacedim>
Tensor<1,spacedim>
FlatManifold<dim, spacedim>::get_tangent_vector (const Point<spacedim> &x1,
                                                 const Point<spacedim> &x2) const
{
  Tensor<1,spacedim> direction = x2-x1;

  // see if we have to take into account periodicity. if so, we need
  // to make sure that if a distance in one coordinate direction
  // is larger than half of the box length, then go the other way
  // around (i.e., via the periodic box)
  for (unsigned int d=0; d<spacedim; ++d)
    if (periodicity[d] > tolerance)
      if (direction[d] < -periodicity[d]/2)
        direction[d] += periodicity[d];
      else if (direction[d] > periodicity[d]/2)
        direction[d] -= periodicity[d];

  return direction;
}

/* -------------------------- ChartManifold --------------------- */

template <int dim, int spacedim, int chartdim>
ChartManifold<dim,spacedim,chartdim>::~ChartManifold ()
{}

template <int dim, int spacedim, int chartdim>
ChartManifold<dim,spacedim,chartdim>::ChartManifold (const Point<chartdim> periodicity):
  sub_manifold(periodicity)
{}

template <int dim, int spacedim, int chartdim>
Point<spacedim>
ChartManifold<dim,spacedim,chartdim>::
get_new_point (const Quadrature<spacedim> &quad) const
{
  const std::vector<Point<spacedim> > &surrounding_points = quad.get_points();
  const std::vector<double> &weights = quad.get_weights();
  std::vector<Point<chartdim> > chart_points(surrounding_points.size());

  for (unsigned int i=0; i<surrounding_points.size(); ++i)
    chart_points[i] = pull_back(surrounding_points[i]);

  const Quadrature<chartdim> chart_quad(chart_points, weights);
  const Point<chartdim> p_chart = sub_manifold.get_new_point(chart_quad);

  return push_forward(p_chart);
}

// explicit instantiations
#include "manifold.inst"

DEAL_II_NAMESPACE_CLOSE

<commit_msg>Avoid a warning about a dangling 'else'.<commit_after>// ---------------------------------------------------------------------
//
// Copyright (C) 1998 - 2015 by the deal.II authors
//
// This file is part of the deal.II library.
//
// The deal.II library is free software; you can use it, redistribute
// it, and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// The full text of the license can be found in the file LICENSE at
// the top level of the deal.II distribution.
//
// ---------------------------------------------------------------------

#include <deal.II/base/tensor.h>
#include <deal.II/grid/manifold.h>
#include <deal.II/grid/tria.h>
#include <deal.II/grid/tria_iterator.h>
#include <deal.II/grid/tria_accessor.h>
#include <deal.II/fe/fe_q.h>
#include <cmath>

DEAL_II_NAMESPACE_OPEN

using namespace Manifolds;

/* -------------------------- Manifold --------------------- */

template <int dim, int spacedim>
Manifold<dim, spacedim>::~Manifold ()
{}

template <int dim, int spacedim>
Point<spacedim>
Manifold<dim, spacedim>::
project_to_manifold (const std::vector<Point<spacedim> > &,
                     const Point<spacedim> &) const
{
  Assert (false, ExcPureFunctionCalled());
  return Point<spacedim>();
}

template <int dim, int spacedim>
Point<spacedim>
Manifold<dim, spacedim>::
get_new_point (const Quadrature<spacedim> &quad) const
{
  Assert(std::abs(std::accumulate(quad.get_weights().begin(), quad.get_weights().end(), 0.0)-1.0) < 1e-10,
         ExcMessage("The weights for the individual points should sum to 1!"));

  Point<spacedim> p;
  for (unsigned int i=0; i<quad.size(); ++i)
    p += quad.weight(i) * quad.point(i);

  return project_to_manifold(quad.get_points(), p);
}

template <int dim, int spacedim>
Point<spacedim>
Manifold<dim, spacedim>::
get_new_point_on_line (const typename Triangulation<dim, spacedim>::line_iterator &line) const
{
  return get_new_point (get_default_quadrature(line));
}

template <int dim, int spacedim>
Point<spacedim>
Manifold<dim, spacedim>::
get_new_point_on_quad (const typename Triangulation<dim, spacedim>::quad_iterator &quad) const
{
  return get_new_point (get_default_quadrature(quad));
}

template <int dim, int spacedim>
Point<spacedim>
Manifold<dim,spacedim>::
get_new_point_on_face (const typename Triangulation<dim,spacedim>::face_iterator &face) const
{
  Assert (dim>1, ExcImpossibleInDim(dim));

  switch (dim)
    {
    case 2:
      return get_new_point_on_line (face);
    case 3:
      return get_new_point_on_quad (face);
    }

  return Point<spacedim>();
}

template <int dim, int spacedim>
Point<spacedim>
Manifold<dim,spacedim>::
get_new_point_on_cell (const typename Triangulation<dim,spacedim>::cell_iterator &cell) const
{
  switch (dim)
    {
    case 1:
      return get_new_point_on_line (cell);
    case 2:
      return get_new_point_on_quad (cell);
    case 3:
      return get_new_point_on_hex (cell);
    }

  return Point<spacedim>();
}

template <>
Point<1>
Manifold<1,1>::
get_new_point_on_face (const Triangulation<1,1>::face_iterator &) const
{
  Assert (false, ExcImpossibleInDim(1));
  return Point<1>();
}

template <>
Point<2>
Manifold<1,2>::
get_new_point_on_face (const Triangulation<1,2>::face_iterator &) const
{
  Assert (false, ExcImpossibleInDim(1));
  return Point<2>();
}

template <>
Point<3>
Manifold<1,3>::
get_new_point_on_face (const Triangulation<1,3>::face_iterator &) const
{
  Assert (false, ExcImpossibleInDim(1));
  return Point<3>();
}

template <>
Point<1>
Manifold<1,1>::
get_new_point_on_quad (const Triangulation<1,1>::quad_iterator &) const
{
  Assert (false, ExcImpossibleInDim(1));
  return Point<1>();
}

template <>
Point<2>
Manifold<1,2>::
get_new_point_on_quad (const Triangulation<1,2>::quad_iterator &) const
{
  Assert (false, ExcImpossibleInDim(1));
  return Point<2>();
}

template <>
Point<3>
Manifold<1,3>::
get_new_point_on_quad (const Triangulation<1,3>::quad_iterator &) const
{
  Assert (false, ExcImpossibleInDim(1));
  return Point<3>();
}

template <int dim, int spacedim>
Point<spacedim>
Manifold<dim, spacedim>::
get_new_point_on_hex (const typename Triangulation<dim, spacedim>::hex_iterator &/*hex*/) const
{
  Assert (false, ExcImpossibleInDim(dim));
  return Point<spacedim>();
}

template <>
Point<3>
Manifold<3,3>::
get_new_point_on_hex (const Triangulation<3, 3>::hex_iterator &hex) const
{
  return get_new_point(get_default_quadrature(hex, true));
}

template <int dim, int spacedim>
Tensor<1,spacedim>
Manifold<dim,spacedim>::get_tangent_vector(const Point<spacedim> &x1,
                                           const Point<spacedim> &x2) const
{
  const double epsilon = 1e-8;

  std::vector<Point<spacedim> > q;
  q.push_back(x1);
  q.push_back(x2);

  std::vector<double> w;
  w.push_back(epsilon);
  w.push_back(1.0-epsilon);

  const Tensor<1,spacedim> neighbor_point = get_new_point (Quadrature<spacedim>(q, w));
  return (neighbor_point-x1)/epsilon;
}

/* -------------------------- FlatManifold --------------------- */

template <int dim, int spacedim>
FlatManifold<dim,spacedim>::FlatManifold (const Point<spacedim> periodicity,
                                          const double tolerance) :
  periodicity(periodicity),
  tolerance(tolerance)
{}

template <int dim, int spacedim>
Point<spacedim>
FlatManifold<dim, spacedim>::
get_new_point (const Quadrature<spacedim> &quad) const
{
  Assert(std::abs(std::accumulate(quad.get_weights().begin(), quad.get_weights().end(), 0.0)-1.0) < 1e-10,
         ExcMessage("The weights for the individual points should sum to 1!"));

  const std::vector<Point<spacedim> > &surrounding_points = quad.get_points();
  const std::vector<double> &weights = quad.get_weights();

  Point<spacedim> p;
  Point<spacedim> dp;
  Point<spacedim> minP = periodicity;
  const bool check_period = (periodicity.norm() > tolerance);
  if (check_period)
    for (unsigned int i=0; i<surrounding_points.size(); ++i)
      for (unsigned int d=0; d<spacedim; ++d)
        {
          minP[d] = std::min(minP[d], surrounding_points[i][d]);
          if (periodicity[d] > 0)
            Assert( (surrounding_points[i][d] < periodicity[d]+tolerance*periodicity.norm()) ||
                    (surrounding_points[i][d] >= -tolerance*periodicity.norm()),
                    ExcPeriodicBox(d, surrounding_points[i], periodicity, tolerance*periodicity.norm()));
        }

  for (unsigned int i=0; i<surrounding_points.size(); ++i)
    {
      dp = Point<spacedim>();
      if (check_period)
        {
          for (unsigned int d=0; d<spacedim; ++d)
            if (periodicity[d] > 0)
              dp[d] = ( (surrounding_points[i][d]-minP[d]) > periodicity[d]/2.0 ?
                        -periodicity[d] : 0.0 );
        }
      p += (surrounding_points[i]+dp)*weights[i];
    }
  if (check_period)
    for (unsigned int d=0; d<spacedim; ++d)
      if (periodicity[d] > 0)
        p[d] = (p[d] < 0 ? p[d] + periodicity[d] : p[d]);

  return project_to_manifold(surrounding_points, p);
}

template <int dim, int spacedim>
Point<spacedim>
FlatManifold<dim, spacedim>::project_to_manifold (const std::vector<Point<spacedim> > &/*vertices*/,
                                                  const Point<spacedim> &candidate) const
{
  return candidate;
}

template <int dim, int spacedim>
Tensor<1,spacedim>
FlatManifold<dim, spacedim>::get_tangent_vector (const Point<spacedim> &x1,
                                                 const Point<spacedim> &x2) const
{
  Tensor<1,spacedim> direction = x2-x1;

  // see if we have to take into account periodicity. if so, we need
  // to make sure that if a distance in one coordinate direction
  // is larger than half of the box length, then go the other way
  // around (i.e., via the periodic box)
  for (unsigned int d=0; d<spacedim; ++d)
    if (periodicity[d] > tolerance)
      {
        if (direction[d] < -periodicity[d]/2)
          direction[d] += periodicity[d];
        else if (direction[d] > periodicity[d]/2)
          direction[d] -= periodicity[d];
      }

  return direction;
}

/* -------------------------- ChartManifold --------------------- */

template <int dim, int spacedim, int chartdim>
ChartManifold<dim,spacedim,chartdim>::~ChartManifold ()
{}

template <int dim, int spacedim, int chartdim>
ChartManifold<dim,spacedim,chartdim>::ChartManifold (const Point<chartdim> periodicity):
  sub_manifold(periodicity)
{}

template <int dim, int spacedim, int chartdim>
Point<spacedim>
ChartManifold<dim,spacedim,chartdim>::
get_new_point (const Quadrature<spacedim> &quad) const
{
  const std::vector<Point<spacedim> > &surrounding_points = quad.get_points();
  const std::vector<double> &weights = quad.get_weights();
  std::vector<Point<chartdim> > chart_points(surrounding_points.size());

  for (unsigned int i=0; i<surrounding_points.size(); ++i)
    chart_points[i] = pull_back(surrounding_points[i]);

  const Quadrature<chartdim> chart_quad(chart_points, weights);
  const Point<chartdim> p_chart = sub_manifold.get_new_point(chart_quad);

  return push_forward(p_chart);
}

// explicit instantiations
#include "manifold.inst"

DEAL_II_NAMESPACE_CLOSE

<|endoftext|>


<commit_before>#include <vector>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <fstream>
#include "overlapgraph.h"

#define VERTEX_INACTIVE 0
#define VERTEX_ACTIVE 1
#define VERTEX_ELIMINATED -1
#define FUZZ 10

using namespace std;

OverlapGraph::OverlapGraph(std::vector<std::string> readvector, std::vector<overlap> overlapvector)
{
	reads = readvector;
	overlaps = overlapvector;
}

void OverlapGraph::initialize()
{
	graph.resize(reads.size());
	reducedGraph.resize(reads.size());
	nonContainedReads.resize(reads.size());
	nonContainedReads.assign(reads.size(), 1);

	for(int i=0;i<overlaps.size();i++)
	{
		overlap o = overlaps[i];

		//removing contained reads
		if(o.ahg > 0 & o.bhg > 0)
			graph[o.read1].push_back(o);
		else if (o.ahg < 0 & o.bhg < 0)
			graph[o.read2].push_back(o);
		else if (o.ahg > 0 & o.bhg < 0)
			nonContainedReads[o.read2] = 0;
		else if (o.ahg < 0 & o.bhg>0)
			nonContainedReads[o.read1] = 0;
	}
}

void OverlapGraph::runUnitigging()
{
	int N = reads.size();

	initialize();

	int *vertexstatus = (int *)malloc(N*sizeof(int));
	memset(vertexstatus, VERTEX_INACTIVE, N*sizeof(int));
	vector< vector<bool> > reduceflags(N);

	for (int i = 0; i < N; i++)
		for (int j = 0; j < graph[i].size(); j++)
			reduceflags[i].push_back(false);

	for (int I = 0; I < N; I++)
	{
		if (graph[I].size() == 0)
			continue;

		for (int j = 0; j < graph[I].size(); j++)
			vertexstatus[graph[I][j].read2] = VERTEX_ACTIVE;

		int longest = 0;
		for (int j = 0; j < graph[I].size(); j++)
		{
			if (graph[I][j].bhg > longest)
				longest = graph[I][j].bhg;
		}

		longest += FUZZ;
		cout << longest << endl;

		for (int j = 0; j < graph[I].size(); j++)
		{
			if (vertexstatus[graph[I][j].read2] == VERTEX_ACTIVE)
			{
				int x = graph[I][j].read2;
				for (int k = 0; k < graph[x].size(); k++)
				{
					if (graph[I][j].bhg + graph[x][k].bhg <= longest)
					{
						if (vertexstatus[graph[x][k].read2] == VERTEX_ACTIVE)
							vertexstatus[graph[x][k].read2] = VERTEX_ELIMINATED;
					}
				}
			}
		}

		for (int j = 0; j < graph[I].size(); j++)
		{
			int x = graph[I][j].read2;
			for (int k = 0; k < graph[x].size(); k++)
			{
				if (graph[x][k].bhg < FUZZ)
				{
					if (vertexstatus[graph[x][k].read2] == VERTEX_ACTIVE)
						vertexstatus[graph[x][k].read2] = VERTEX_ELIMINATED;
				}
			}
		}

		for (int j = 0; j < graph[I].size(); j++)
		{
			if (vertexstatus[graph[I][j].read2] == VERTEX_ELIMINATED)
			{
				reduceflags[I][j] = true;
			}
			vertexstatus[graph[I][j].read2] == VERTEX_INACTIVE;
		}
	}

	for(int i=0;i<graph.size();i++)
    {
        for(int j=0;j<graph[i].size();j++)
        {
			if (!reduceflags[i][j] & nonContainedReads[graph[i][j].read1] & nonContainedReads[graph[i][j].read2]){
				// Add edge to the reduced graph
				reducedGraph[i].push_back(graph[i][j]);
				cout << graph[i][j].read1 << " -> " << graph[i][j].read2 << endl;
			}
        }
    }
	uniqueJoinCollapsing();

	free(vertexstatus);
	return;
}

void OverlapGraph::printLayouts()
{
	ofstream output("layouts.afg");
	int *offsets = (int *)malloc(reads.size()*sizeof(int));
	memset(offsets, 0, reads.size()*sizeof(int));

	for (int i = 0; i < reads.size(); i++)
	{
		for (int j = 0; j < graph[i].size(); j++)
		{
			overlap o = graph[i][j];
			if (nonContainedReads[o.read1] & nonContainedReads[o.read2]) {
				offsets[o.read2] = offsets[o.read1] + o.ahg;
			}
		}
	}
}

void OverlapGraph::uniqueJoinCollapsing(){

	reducedGraphVertexReferenceCounter.assign(reducedGraph.size(), 0);

	// Calculate references to vertexes
	for (int i = 0; i < reducedGraph.size(); i++){
		for (int j = 0; j < reducedGraph[i].size(); j++){
			reducedGraphVertexReferenceCounter[reducedGraph[i][j].read2]++;
		}
	}

	// Find first "juncture" vertex
	int startingVertex = 0;
	bool startingVertexFound = false;
	while (startingVertex < reducedGraph.size()){
		if (reducedGraph[startingVertex].size() > 0){
			startingVertexFound = true;
			break;
		}
		startingVertex++;
	}
	if (startingVertexFound){
		calculateChunks(startingVertex);
	}
}

void OverlapGraph::calculateChunks(int chunkStartingVertexId){

	int currentVertexId = chunkStartingVertexId;

	if (vertexAlreadyInChunk(currentVertexId)){
		return;
	}

	// create new chunk
	Chunk chunk;

	while (true){
		if (reducedGraphVertexReferenceCounter[currentVertexId] > 1 && currentVertexId != chunkStartingVertexId){
			// special case: juncture vertex (not part of our chunk)
			calculateChunks(currentVertexId);
			break;
		}

		chunk.members.push_back(currentVertexId);

		if (reducedGraph[currentVertexId].size() < 1){
			// dead end
			break;
		}

		if (reducedGraph[currentVertexId].size() > 1){
			// juncture point - each path vertex represents a new chunk start
			for (int i = 0; i < reducedGraph[currentVertexId].size(); i++){
				calculateChunks(reducedGraph[currentVertexId][i].read2);
			}
			break;
		}

		currentVertexId = reducedGraph[currentVertexId][0].read2;
	}
	collapsedReducedGraph.push_back(chunk);

	return;
}

bool OverlapGraph::vertexAlreadyInChunk(int vertexId){
	for (int i = 0; i < collapsedReducedGraph.size(); ++i){
		for (int j = 0; j < collapsedReducedGraph[i].members.size(); ++j){
			if (vertexId == collapsedReducedGraph[i].members[j]){
				return true;
			}
		}
	}
	return false;
}<commit_msg>printLayouts output<commit_after>#include <vector>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <fstream>
#include "overlapgraph.h"

#define VERTEX_INACTIVE 0
#define VERTEX_ACTIVE 1
#define VERTEX_ELIMINATED -1
#define FUZZ 10

using namespace std;

OverlapGraph::OverlapGraph(std::vector<std::string> readvector, std::vector<overlap> overlapvector)
{
	reads = readvector;
	overlaps = overlapvector;
}

void OverlapGraph::initialize()
{
	graph.resize(reads.size());
	reducedGraph.resize(reads.size());
	nonContainedReads.resize(reads.size());
	nonContainedReads.assign(reads.size(), 1);

	for(int i=0;i<overlaps.size();i++)
	{
		overlap o = overlaps[i];

		//removing contained reads
		if(o.ahg > 0 & o.bhg > 0)
			graph[o.read1].push_back(o);
		else if (o.ahg < 0 & o.bhg < 0)
			graph[o.read2].push_back(o);
		else if (o.ahg > 0 & o.bhg < 0)
			nonContainedReads[o.read2] = 0;
		else if (o.ahg < 0 & o.bhg>0)
			nonContainedReads[o.read1] = 0;
	}
}

void OverlapGraph::runUnitigging()
{
	int N = reads.size();

	initialize();

	int *vertexstatus = (int *)malloc(N*sizeof(int));
	memset(vertexstatus, VERTEX_INACTIVE, N*sizeof(int));
	vector< vector<bool> > reduceflags(N);

	for (int i = 0; i < N; i++)
		for (int j = 0; j < graph[i].size(); j++)
			reduceflags[i].push_back(false);

	for (int I = 0; I < N; I++)
	{
		if (graph[I].size() == 0)
			continue;

		for (int j = 0; j < graph[I].size(); j++)
			vertexstatus[graph[I][j].read2] = VERTEX_ACTIVE;

		int longest = 0;
		for (int j = 0; j < graph[I].size(); j++)
		{
			if (graph[I][j].bhg > longest)
				longest = graph[I][j].bhg;
		}

		longest += FUZZ;
		cout << longest << endl;

		for (int j = 0; j < graph[I].size(); j++)
		{
			if (vertexstatus[graph[I][j].read2] == VERTEX_ACTIVE)
			{
				int x = graph[I][j].read2;
				for (int k = 0; k < graph[x].size(); k++)
				{
					if (graph[I][j].bhg + graph[x][k].bhg <= longest)
					{
						if (vertexstatus[graph[x][k].read2] == VERTEX_ACTIVE)
							vertexstatus[graph[x][k].read2] = VERTEX_ELIMINATED;
					}
				}
			}
		}

		for (int j = 0; j < graph[I].size(); j++)
		{
			int x = graph[I][j].read2;
			for (int k = 0; k < graph[x].size(); k++)
			{
				if (graph[x][k].bhg < FUZZ)
				{
					if (vertexstatus[graph[x][k].read2] == VERTEX_ACTIVE)
						vertexstatus[graph[x][k].read2] = VERTEX_ELIMINATED;
				}
			}
		}

		for (int j = 0; j < graph[I].size(); j++)
		{
			if (vertexstatus[graph[I][j].read2] == VERTEX_ELIMINATED)
			{
				reduceflags[I][j] = true;
			}
			vertexstatus[graph[I][j].read2] == VERTEX_INACTIVE;
		}
	}

	for(int i=0;i<graph.size();i++)
    {
        for(int j=0;j<graph[i].size();j++)
        {
			if (!reduceflags[i][j] & nonContainedReads[graph[i][j].read1] & nonContainedReads[graph[i][j].read2]){
				// Add edge to the reduced graph
				reducedGraph[i].push_back(graph[i][j]);
				cout << graph[i][j].read1 << " -> " << graph[i][j].read2 << endl;
			}
        }
    }
	uniqueJoinCollapsing();

	free(vertexstatus);
	return;
}

void OverlapGraph::printLayouts()
{
	ofstream output("layouts.afg");
	int *offsets = (int *)malloc(reads.size()*sizeof(int));
	memset(offsets, 0, reads.size()*sizeof(int));

	for (int i = 0; i < reads.size(); i++)
	{
		for (int j = 0; j < graph[i].size(); j++)
		{
			overlap o = graph[i][j];
			if (nonContainedReads[o.read1] & nonContainedReads[o.read2]) {
				offsets[o.read2] = offsets[o.read1] + o.ahg;
			}
		}
	}

	output << "{LAY" << endl;
	for (int i = 0; i < reads.size(); i++)
	{

	}
}

void OverlapGraph::uniqueJoinCollapsing(){

	reducedGraphVertexReferenceCounter.assign(reducedGraph.size(), 0);

	// Calculate references to vertexes
	for (int i = 0; i < reducedGraph.size(); i++){
		for (int j = 0; j < reducedGraph[i].size(); j++){
			reducedGraphVertexReferenceCounter[reducedGraph[i][j].read2]++;
		}
	}

	// Find first "juncture" vertex
	int startingVertex = 0;
	bool startingVertexFound = false;
	while (startingVertex < reducedGraph.size()){
		if (reducedGraph[startingVertex].size() > 0){
			startingVertexFound = true;
			break;
		}
		startingVertex++;
	}
	if (startingVertexFound){
		calculateChunks(startingVertex);
	}
}

void OverlapGraph::calculateChunks(int chunkStartingVertexId){

	int currentVertexId = chunkStartingVertexId;

	if (vertexAlreadyInChunk(currentVertexId)){
		return;
	}

	// create new chunk
	Chunk chunk;

	while (true){
		if (reducedGraphVertexReferenceCounter[currentVertexId] > 1 && currentVertexId != chunkStartingVertexId){
			// special case: juncture vertex (not part of our chunk)
			calculateChunks(currentVertexId);
			break;
		}

		chunk.members.push_back(currentVertexId);

		if (reducedGraph[currentVertexId].size() < 1){
			// dead end
			break;
		}

		if (reducedGraph[currentVertexId].size() > 1){
			// juncture point - each path vertex represents a new chunk start
			for (int i = 0; i < reducedGraph[currentVertexId].size(); i++){
				calculateChunks(reducedGraph[currentVertexId][i].read2);
			}
			break;
		}

		currentVertexId = reducedGraph[currentVertexId][0].read2;
	}
	collapsedReducedGraph.push_back(chunk);

	return;
}

bool OverlapGraph::vertexAlreadyInChunk(int vertexId){
	for (int i = 0; i < collapsedReducedGraph.size(); ++i){
		for (int j = 0; j < collapsedReducedGraph[i].members.size(); ++j){
			if (vertexId == collapsedReducedGraph[i].members[j]){
				return true;
			}
		}
	}
	return false;
}<|endoftext|>


<commit_before><commit_msg>VS 2015 seems to support this-qualifiers, so we use them<commit_after><|endoftext|>


<commit_before>/*
Copyright (c) 2014, Scott Zuyderduyn
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/

//----------------------------------------------------------------------------
// cube.hpp
// An STL-like structure that resides in video memory.
//
// Author: Scott D. Zuyderduyn, Ph.D. (scott.zuyderduyn@utoronto.ca)
//----------------------------------------------------------------------------
#pragma once
#ifndef ECUDA_CUBE_HPP
#define ECUDA_CUBE_HPP

#include <limits>
#include <vector>
#include <estd/cube.hpp>
#include "global.hpp"
#include "containers.hpp"
//#include "iterators.hpp"
#include "matrix.hpp"
#include "memory.hpp"

namespace ecuda {

template<typename T>
class cube {

public:
	typedef T value_type;
	typedef T* pointer;
	typedef const T* const_pointer;
	typedef T& reference;
	typedef const T& const_reference;
	typedef std::ptrdiff_t difference_type;
	typedef std::size_t size_type;

	typedef ecuda::OffsettingContainer< cube<T> > xy_type;
	typedef ecuda::OffsettingContainer< cube<T> > xz_type;
	typedef ecuda::OffsettingContainer< cube<T> > yz_type;
	typedef const ecuda::OffsettingContainer< const cube<T>, size_type, const_pointer > const_xy_type;
	typedef const ecuda::OffsettingContainer< const cube<T>, size_type, const_pointer > const_xz_type;
	typedef const ecuda::OffsettingContainer< const cube<T>, size_type, const_pointer > const_yz_type;

	typedef ecuda::CubeSliceContainer< cube<T>, size_type, pointer > matrix_type;
	typedef const ecuda::CubeSliceContainer< const cube<T>, size_type, const_pointer > const_matrix_type;

private:
	// REMEMBER: numberRows, numberColumns, numberDepths and pitch altered on device memory won't be
	//           reflected on the host object. Don't allow the device to perform any operations that
	//           change their value.
	size_type numberRows;
	size_type numberColumns;
	size_type numberDepths;
	size_type pitch;
	device_ptr<T> deviceMemory;
	//unique_ptr< matrix<T>[] > matrices;

public:
	HOST cube( const size_type numberRows=0, const size_type numberColumns=0, const size_type numberDepths=0, const T& value = T() ) : numberRows(numberRows), numberColumns(numberColumns), numberDepths(numberDepths) {
		if( numberRows and numberColumns and numberDepths ) {
			CUDA_CALL( cudaMallocPitch( deviceMemory.alloc_ptr(), &pitch, numberColumns*numberDepths*sizeof(T), numberRows ) );
			std::vector<T> v( numberColumns*numberDepths, value );
			for( size_t i = 0; i < numberRows; ++i )
				CUDA_CALL( cudaMemcpy2D( deviceMemory.get()+(i*pitch/sizeof(T)), numberColumns*numberDepths*sizeof(T), &v[0], numberColumns*numberDepths*sizeof(T), numberColumns*numberDepths*sizeof(T), 1, cudaMemcpyHostToDevice ) );
		}
	}
	HOST DEVICE cube( const cube<T>& src ) : numberRows(src.numberRows), numberColumns(src.numberColumns), numberDepths(src.numberDepths), pitch(src.pitch), deviceMemory(src.deviceMemory) {}
	template<typename U,typename V,typename W>
	HOST cube( const estd::cube<T,U,V,W>& src ) : numberRows(src.row_size()), numberColumns(src.column_size()), numberDepths(src.depth_size()) {
		if( numberRows and numberColumns and numberDepths ) {
			CUDA_CALL( cudaMallocPitch( deviceMemory.alloc_ptr(), &pitch, numberColumns*numberDepths*sizeof(T), numberRows ) );
			for( size_t i = 0; i < numberRows; ++i ) {
				std::vector<T> v; v.reserve( numberColumns*numberDepths );
				for( size_t j = 0; j < numberColumns; ++j )
					for( size_t k = 0; k < numberDepths; ++k )
						v.push_back( src[i][j][k] );
				CUDA_CALL( cudaMemcpy2D( deviceMemory.get()+(i*pitch/sizeof(T)), numberColumns*numberDepths*sizeof(T), &v[0], numberColumns*numberDepths*sizeof(T), numberColumns*numberDepths*sizeof(T), 1, cudaMemcpyHostToDevice ) );
			}
		}
	}

	// capacity:
	HOST DEVICE inline size_type row_size() const __NOEXCEPT__ { return numberRows; }
	HOST DEVICE inline size_type column_size() const __NOEXCEPT__ { return numberColumns; }
	HOST DEVICE inline size_type depth_size() const __NOEXCEPT__ { return numberDepths; }
	HOST DEVICE inline size_type get_pitch() const { return pitch; }
	HOST DEVICE inline size_type size() const __NOEXCEPT__ { return row_size()*column_size()*depth_size(); }
	HOST DEVICE inline bool empty() const __NOEXCEPT__ { return !size(); }

	// element access:
	DEVICE inline reference at( const size_type rowIndex, const size_type columnIndex, const size_type depthIndex ) { return *(deviceMemory.get()+(rowIndex*pitch/sizeof(T)+columnIndex*numberDepths+depthIndex)); }
	DEVICE inline reference at( const size_type index ) { return at( index/(numberColumns*numberDepths), (index % (numberColumns*numberDepths))/numberDepths, (index % (numberColumns*numberDepths)) % numberDepths ); }
	DEVICE inline const_reference at( const size_type rowIndex, const size_type columnIndex, const size_type depthIndex ) const { return *(deviceMemory.get()+(rowIndex*pitch/sizeof(T)+columnIndex*numberDepths+depthIndex)); }
	DEVICE inline const_reference at( const size_type index ) const { return at( index/(numberColumns*numberDepths), (index % (numberColumns*numberDepths))/numberDepths, (index % (numberColumns*numberDepths)) % numberDepths ); }
	HOST DEVICE inline pointer data() __NOEXCEPT__ { return deviceMemory.get(); }
	HOST DEVICE inline const_pointer data() const __NOEXCEPT__ { return deviceMemory.get(); }

	HOST DEVICE inline matrix_type get_row( const size_type rowIndex ) { return matrix_type( *this, rowIndex ); }
	HOST DEVICE inline const_matrix_type get_row( const size_type rowIndex ) const { return const_matrix_type( *this, rowIndex ); }
	HOST DEVICE inline matrix_type operator[]( const size_type rowIndex ) { return get_row(rowIndex); }
	HOST DEVICE inline const_matrix_type operator[]( const size_type rowIndex ) const { return get_row(rowIndex); }

	//xy_type get_xy( const RowIndexType x, const ColumnIndexType y ) { return contents[x].get_row(y); }
	//xz_type get_xz( const RowIndexType x, const DepthIndexType z ) { return contents[x].get_column(z); }
	//yz_type get_yz( const ColumnIndexType y, const DepthIndexType z ) {	return OffsettingContainer< cube<CellType,RowIndexType,ColumnIndexType,DepthIndexType> >( *this, row_size(), y*depth_size()+z, column_size()*depth_size() ); }
	//const_xy_type get_xy( const RowIndexType x, const ColumnIndexType y ) const { return contents[x].get_row(y); }
	//const_xz_type get_xz( const RowIndexType x, const DepthIndexType z ) const { return contents[x].get_column(z); }
	//const_yz_type get_yz( const ColumnIndexType y, const DepthIndexType z ) const { return OffsettingContainer< const cube<CellType,RowIndexType,ColumnIndexType,DepthIndexType> >( *this, row_size(), y*depth_size()+z, column_size()*depth_size() ); }

	template<typename U,typename V,typename W>
	HOST cube<T>& operator>>( estd::cube<T,U,V,W>& dest ) {
		dest.resize( static_cast<U>(numberRows), static_cast<V>(numberColumns), static_cast<W>(numberDepths) );
		for( size_type i = 0; i < numberRows; ++i ) operator[](i) >> dest[i];
		return *this;
	}

};

} // namespace ecuda

#endif

<commit_msg>added note about non-functional device-to-host cube transfer<commit_after>/*
Copyright (c) 2014, Scott Zuyderduyn
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/

//----------------------------------------------------------------------------
// cube.hpp
// An STL-like structure that resides in video memory.
//
// Author: Scott D. Zuyderduyn, Ph.D. (scott.zuyderduyn@utoronto.ca)
//----------------------------------------------------------------------------
#pragma once
#ifndef ECUDA_CUBE_HPP
#define ECUDA_CUBE_HPP

#include <limits>
#include <vector>
#include <estd/cube.hpp>
#include "global.hpp"
#include "containers.hpp"
//#include "iterators.hpp"
#include "matrix.hpp"
#include "memory.hpp"

namespace ecuda {

template<typename T>
class cube {

public:
	typedef T value_type;
	typedef T* pointer;
	typedef const T* const_pointer;
	typedef T& reference;
	typedef const T& const_reference;
	typedef std::ptrdiff_t difference_type;
	typedef std::size_t size_type;

	typedef ecuda::OffsettingContainer< cube<T> > xy_type;
	typedef ecuda::OffsettingContainer< cube<T> > xz_type;
	typedef ecuda::OffsettingContainer< cube<T> > yz_type;
	typedef const ecuda::OffsettingContainer< const cube<T>, size_type, const_pointer > const_xy_type;
	typedef const ecuda::OffsettingContainer< const cube<T>, size_type, const_pointer > const_xz_type;
	typedef const ecuda::OffsettingContainer< const cube<T>, size_type, const_pointer > const_yz_type;

	typedef ecuda::CubeSliceContainer< cube<T>, size_type, pointer > matrix_type;
	typedef const ecuda::CubeSliceContainer< const cube<T>, size_type, const_pointer > const_matrix_type;

private:
	// REMEMBER: numberRows, numberColumns, numberDepths and pitch altered on device memory won't be
	//           reflected on the host object. Don't allow the device to perform any operations that
	//           change their value.
	size_type numberRows;
	size_type numberColumns;
	size_type numberDepths;
	size_type pitch;
	device_ptr<T> deviceMemory;
	//unique_ptr< matrix<T>[] > matrices;

public:
	HOST cube( const size_type numberRows=0, const size_type numberColumns=0, const size_type numberDepths=0, const T& value = T() ) : numberRows(numberRows), numberColumns(numberColumns), numberDepths(numberDepths) {
		if( numberRows and numberColumns and numberDepths ) {
			CUDA_CALL( cudaMallocPitch( deviceMemory.alloc_ptr(), &pitch, numberColumns*numberDepths*sizeof(T), numberRows ) );
			std::vector<T> v( numberColumns*numberDepths, value );
			for( size_t i = 0; i < numberRows; ++i )
				CUDA_CALL( cudaMemcpy2D( deviceMemory.get()+(i*pitch/sizeof(T)), numberColumns*numberDepths*sizeof(T), &v[0], numberColumns*numberDepths*sizeof(T), numberColumns*numberDepths*sizeof(T), 1, cudaMemcpyHostToDevice ) );
		}
	}
	HOST DEVICE cube( const cube<T>& src ) : numberRows(src.numberRows), numberColumns(src.numberColumns), numberDepths(src.numberDepths), pitch(src.pitch), deviceMemory(src.deviceMemory) {}
	template<typename U,typename V,typename W>
	HOST cube( const estd::cube<T,U,V,W>& src ) : numberRows(src.row_size()), numberColumns(src.column_size()), numberDepths(src.depth_size()) {
		if( numberRows and numberColumns and numberDepths ) {
			CUDA_CALL( cudaMallocPitch( deviceMemory.alloc_ptr(), &pitch, numberColumns*numberDepths*sizeof(T), numberRows ) );
			for( size_t i = 0; i < numberRows; ++i ) {
				std::vector<T> v; v.reserve( numberColumns*numberDepths );
				for( size_t j = 0; j < numberColumns; ++j )
					for( size_t k = 0; k < numberDepths; ++k )
						v.push_back( src[i][j][k] );
				CUDA_CALL( cudaMemcpy2D( deviceMemory.get()+(i*pitch/sizeof(T)), numberColumns*numberDepths*sizeof(T), &v[0], numberColumns*numberDepths*sizeof(T), numberColumns*numberDepths*sizeof(T), 1, cudaMemcpyHostToDevice ) );
			}
		}
	}

	// capacity:
	HOST DEVICE inline size_type row_size() const __NOEXCEPT__ { return numberRows; }
	HOST DEVICE inline size_type column_size() const __NOEXCEPT__ { return numberColumns; }
	HOST DEVICE inline size_type depth_size() const __NOEXCEPT__ { return numberDepths; }
	HOST DEVICE inline size_type get_pitch() const { return pitch; }
	HOST DEVICE inline size_type size() const __NOEXCEPT__ { return row_size()*column_size()*depth_size(); }
	HOST DEVICE inline bool empty() const __NOEXCEPT__ { return !size(); }

	// element access:
	DEVICE inline reference at( const size_type rowIndex, const size_type columnIndex, const size_type depthIndex ) { return *(deviceMemory.get()+(rowIndex*pitch/sizeof(T)+columnIndex*numberDepths+depthIndex)); }
	DEVICE inline reference at( const size_type index ) { return at( index/(numberColumns*numberDepths), (index % (numberColumns*numberDepths))/numberDepths, (index % (numberColumns*numberDepths)) % numberDepths ); }
	DEVICE inline const_reference at( const size_type rowIndex, const size_type columnIndex, const size_type depthIndex ) const { return *(deviceMemory.get()+(rowIndex*pitch/sizeof(T)+columnIndex*numberDepths+depthIndex)); }
	DEVICE inline const_reference at( const size_type index ) const { return at( index/(numberColumns*numberDepths), (index % (numberColumns*numberDepths))/numberDepths, (index % (numberColumns*numberDepths)) % numberDepths ); }
	HOST DEVICE inline pointer data() __NOEXCEPT__ { return deviceMemory.get(); }
	HOST DEVICE inline const_pointer data() const __NOEXCEPT__ { return deviceMemory.get(); }

	HOST DEVICE inline matrix_type get_row( const size_type rowIndex ) { return matrix_type( *this, rowIndex ); }
	HOST DEVICE inline const_matrix_type get_row( const size_type rowIndex ) const { return const_matrix_type( *this, rowIndex ); }
	HOST DEVICE inline matrix_type operator[]( const size_type rowIndex ) { return get_row(rowIndex); }
	HOST DEVICE inline const_matrix_type operator[]( const size_type rowIndex ) const { return get_row(rowIndex); }

	//xy_type get_xy( const RowIndexType x, const ColumnIndexType y ) { return contents[x].get_row(y); }
	//xz_type get_xz( const RowIndexType x, const DepthIndexType z ) { return contents[x].get_column(z); }
	//yz_type get_yz( const ColumnIndexType y, const DepthIndexType z ) {	return OffsettingContainer< cube<CellType,RowIndexType,ColumnIndexType,DepthIndexType> >( *this, row_size(), y*depth_size()+z, column_size()*depth_size() ); }
	//const_xy_type get_xy( const RowIndexType x, const ColumnIndexType y ) const { return contents[x].get_row(y); }
	//const_xz_type get_xz( const RowIndexType x, const DepthIndexType z ) const { return contents[x].get_column(z); }
	//const_yz_type get_yz( const ColumnIndexType y, const DepthIndexType z ) const { return OffsettingContainer< const cube<CellType,RowIndexType,ColumnIndexType,DepthIndexType> >( *this, row_size(), y*depth_size()+z, column_size()*depth_size() ); }

	template<typename U,typename V,typename W>
	HOST cube<T>& operator>>( estd::cube<T,U,V,W>& dest ) {
		//TODO: this needs to be re-implemented, it won't work as currently written
		dest.resize( static_cast<U>(numberRows), static_cast<V>(numberColumns), static_cast<W>(numberDepths) );
		for( size_type i = 0; i < numberRows; ++i ) operator[](i) >> dest[i];
		return *this;
	}

};

} // namespace ecuda

#endif

<|endoftext|>