<commit_before>#include "systems.h"
#include "compiler.h"
#include "mswin.h"
#include "resources.h"
#include "vector.h"
#include "make_system.h"
#include "cramer.h"
#include "graphics.h"
#include "memory.h"
#include <cstdint>

struct triangle_t
{
  float xyz [3] [4]; // Co-ordinates for a single triangle XYZ of the Moebius tiling.
  float abc [8] [4]; // Coefficients A, B, C for the generator T = AX + BY + CZ.
};

// The fundamental triangle of the tiling has angles
// A = pi/p, B = pi/q, C = pi/r and sides a, b, c.

// By the spherical cosine rule,
// cosa = (cosA + cosB * cosC) / (sinB * sinC),
// cosb = (cosB + cosC * cosA) / (sinC * sinA),
// cosc = (cosC + cosA * cosB) / (sinA * sinB).

// We assume p = 2; thus cosA = 0 and sinA = 1. Therefore,
// cosa = (cosB * cosC) / (sinB * sinC),
// cosb = cosB / sinC,
// cosc = cosC / sinB.

// Any triple (alpha, beta, gamma) identifies a point T relative to
// the spherical triangle XYZ, by the formula
// T = alpha * X + beta * Y + gamma * Z.
// For certain triples, replicating the point T in each triangle
// of the tiling gives the vertices of a uniform polyhedron:

// { 1, 0, 0, },             Point X.
// { 0, 1, 0, },             Point Y.
// { 0, 0, 1, },             Point Z.
// { 0, sinb, sinc, },       Intersection of YZ with the angular bisector of corner X.
// { sina, 0, sinc, },       Intersection of ZX with the angular bisector of corner Y.
// { sina, sinb, 0, },       Intersection of YZ with the angular bisector of corner Z.
// { sinA, sinB, sinC, },    Incentre (intersection of the three bisectors).
// { alpha, beta, gamma, },  Snub generator.

//     X1
//    /  \    Part of the tiling of the sphere, showing
//   Z0--Y0   the triangle X0-Y0-Z0 and the adjacent triangles.
//   |\  /|
//   | X0 |
//   |/  \|
//   Y1  Z1

// For the snub generator, the three points
//   TX = alpha * X1 + beta * Y0 + gamma * Z0
//   TY = alpha * X0 + beta * Y1 + gamma * Z0
//   TZ = alpha * X0 + beta * Y0 + gamma * Z1
// (see diagram) are the vertices of an equilateral spherical triangle.

triangle_t triangles [3] ALIGNED16 =
{
  // Tetrahedral, <2, 3, 3>.
  {
    { { +0x1.000000P+0f, +0x0.000000P+0f, +0x0.000000P+0f, 0.0f, },
      { +0x1.279a74P-1f, +0x1.a20bd8P-1f, +0x0.000000P+0f, 0.0f, },
      { +0x1.279a74P-1f, +0x0.000000P+0f, +0x1.a20bd8P-1f, 0.0f, },
    },
    { { +0x1.000000P+0f, +0x0.000000P+0f, +0x0.000000P+0f, 0.0f, },
      { +0x0.000000P+0f, +0x1.000000P+0f, +0x0.000000P+0f, 0.0f, },
      { +0x0.000000P+0f, +0x0.000000P+0f, +0x1.000000P+0f, 0.0f, },
      { +0x0.000000P+0f, +0x1.3988e2P-1f, +0x1.3988e2P-1f, 0.0f, },
      { +0x1.34bf64P-1f, +0x0.000000P+0f, +0x1.0b621eP-1f, 0.0f, },
      { +0x1.34bf64P-1f, +0x1.0b621eP-1f, +0x0.000000P+0f, 0.0f, },
      { +0x1.c9f25cP-2f, +0x1.8c97f0P-2f, +0x1.8c97f0P-2f, 0.0f, },
      { +0x1.4cb7c0P-2f, +0x1.d2393eP-2f, +0x1.d2393eP-2f, 0.0f, },
    },
  },
  // Octahedral, <2, 4, 3>.
  // Aligned so that two octahedral triangles cover one tetrahedral triangle.
  {
    { { +0x1.6a09e6P-1f, +0x1.000000P-1f, +0x1.000000P-1f, 0.0f, },
      { +0x1.000000P+0f, +0x0.000000P+0f, +0x0.000000P+0f, 0.0f, },
      { +0x1.279a74P-1f, +0x1.a20bd8P-1f, +0x0.000000P+0f, 0.0f, },
    },
    { { +0x1.000000P+0f, +0x0.000000P+0f, +0x0.000000P+0f, 0.0f, },
      { +0x0.000000P+0f, +0x1.000000P+0f, +0x0.000000P+0f, 0.0f, },
      { +0x0.000000P+0f, +0x0.000000P+0f, +0x1.000000P+0f, 0.0f, },
      { +0x0.000000P+0f, +0x1.02ca46P-1f, +0x1.3cf3aeP-1f, 0.0f, },
      { +0x1.1fd4a6P-1f, +0x0.000000P+0f, +0x1.f28990P-2f, 0.0f, },
      { +0x1.43d136P-1f, +0x1.c9f25cP-2f, +0x0.000000P+0f, 0.0f, },
      { +0x1.b9d594P-2f, +0x1.386c8eP-2f, +0x1.7ea3c6P-2f, 0.0f, },
      { +0x1.31816eP-2f, +0x1.8d5502P-2f, +0x1.bdd092P-2f, 0.0f, },
    },
  },
  // Icosahedral, <2, 5, 3>.
  {
    { { +0x1.000000P+0f, +0x0.000000P+0f, +0x0.000000P+0f, 0.0f, },
      { +0x1.b38880P-1f, +0x1.0d2ca0P-1f, +0x0.000000P+0f, 0.0f, },
      { +0x1.de4bd6P-1f, +0x0.0000000P+0, +0x1.6d62c6P-2f, 0.0f, },
    },
    { { +0x1.000000P+0f, +0x0.000000P+0f, +0x0.000000P+0f, 0.0f, },
      { +0x0.000000P+0f, +0x1.000000P+0f, +0x0.000000P+0f, 0.0f, },
      { +0x0.000000P+0f, +0x0.000000P+0f, +0x1.000000P+0f, 0.0f, },
      { +0x0.000000P+0f, +0x1.b4242aP-2f, +0x1.414c80P-1f, 0.0f, },
      { +0x1.16fc4eP-1f, +0x0.000000P+0f, +0x1.e33798P-2f, 0.0f, },
      { +0x1.4e5014P-1f, +0x1.890220P-2f, +0x0.000000P+0f, 0.0f, },
      { +0x1.b3be36P-2f, +0x1.001f92P-2f, +0x1.795d50P-2f, 0.0f, },
      { +0x1.287f1eP-2f, +0x1.52a52eP-2f, +0x1.b882c6P-2f, 0.0f, },
    },
  }
};

// Turn a PQR triangle into a PRQ triangle.
void reflect (triangle_t & t)
{
  v4f x = load4f (t.xyz [0]);
  v4f y = load4f (t.xyz [1]);
  v4f z = load4f (t.xyz [2]);

  v4f n = normalize (cross (x, y));
  v4f d = dot (n, z) * n;

  store4f (t.xyz [1], z - (d + d));
  store4f (t.xyz [2], y);

  for (unsigned k = 0; k != 8; ++ k) {
    v4f a = load4f (t.abc [k]);
    store4f (t.abc [k], _mm_shuffle_ps (a, a, SHUFFLE (0, 2, 1, 3)));
  }
}

template <unsigned K>
ALWAYS_INLINE inline void copy (const float (* from) [4], float (& to) [K] [4])
{
  for (unsigned k = 0; k != K; ++ k) {
    store4f (to [k], load4f (from [k]));
  }
}

void initialize_systems (float (& abc) [system_count] [8] [4],
                         float (& xyz) [system_count] [3] [4],
                         float (& xyzinvt) [system_count] [3] [4],
                         unsigned (& primitive_count) [system_count],
                         unsigned (& vao_ids) [system_count])
{
  auto init = [&] (const triangle_t & t, system_select_t select, unsigned q, unsigned r) -> void
  {
    copy (t.xyz, xyz [select]);
    copy (t.abc, abc [select]);
    cramer::inverse_transpose (xyz [select], xyzinvt [select]);
    unsigned p = 2, N = 2 * p * q * r / (q * r + r * p + p * q - p * q * r);
    unsigned indices [60] [6];
    ALIGNED16 float nodes [62] [4];
    make_system (q, r, t.xyz, nodes, indices);
    vao_ids [select] = make_vao (N, nodes, indices);
    primitive_count [select] = N;
  };

  for (unsigned n = 0; n != 3; ++ n) {
    triangle_t & triangle = triangles [n];
    init (triangle, system_select_t (2 * n + 0), 3 + n, 3);
    reflect (triangle);
    init (triangle, system_select_t (2 * n + 1), 3, 3 + n);
  }
}
<commit_msg>systems.cpp: co-ordinates for the great icosahedron as a snubified tetrahedron.<commit_after>#include "systems.h"
#include "compiler.h"
#include "mswin.h"
#include "resources.h"
#include "vector.h"
#include "make_system.h"
#include "cramer.h"
#include "graphics.h"
#include "memory.h"
#include <cstdint>

struct triangle_t
{
  float xyz [3] [4]; // Co-ordinates for a single triangle XYZ of the Moebius tiling.
  float abc [8] [4]; // Coefficients A, B, C for the generator T = AX + BY + CZ.
};

// The fundamental triangle of the tiling has angles
// A = pi/p, B = pi/q, C = pi/r and sides a, b, c.

// By the spherical cosine rule,
// cosa = (cosA + cosB * cosC) / (sinB * sinC),
// cosb = (cosB + cosC * cosA) / (sinC * sinA),
// cosc = (cosC + cosA * cosB) / (sinA * sinB).

// We assume p = 2; thus cosA = 0 and sinA = 1. Therefore,
// cosa = (cosB * cosC) / (sinB * sinC),
// cosb = cosB / sinC,
// cosc = cosC / sinB.

// Any triple (alpha, beta, gamma) identifies a point T relative to
// the spherical triangle XYZ, by the formula
// T = alpha * X + beta * Y + gamma * Z.
// For certain triples, replicating the point T in each triangle
// of the tiling gives the vertices of a uniform polyhedron:

// { 1, 0, 0, },             Point X.
// { 0, 1, 0, },             Point Y.
// { 0, 0, 1, },             Point Z.
// { 0, sinb, sinc, },       Intersection of YZ with the angular bisector of corner X.
// { sina, 0, sinc, },       Intersection of ZX with the angular bisector of corner Y.
// { sina, sinb, 0, },       Intersection of YZ with the angular bisector of corner Z.
// { sinA, sinB, sinC, },    Incentre (intersection of the three bisectors).
// { alpha, beta, gamma, },  Snub generator.

//     X1
//    /  \    Part of the tiling of the sphere, showing
//   Z0--Y0   the triangle X0-Y0-Z0 and the adjacent triangles.
//   |\  /|
//   | X0 |
//   |/  \|
//   Y1  Z1

// For the snub generator, the three points
//   TX = alpha * X1 + beta * Y0 + gamma * Z0
//   TY = alpha * X0 + beta * Y1 + gamma * Z0
//   TZ = alpha * X0 + beta * Y0 + gamma * Z1
// (see diagram) are the vertices of an equilateral spherical triangle.

triangle_t triangles [3] ALIGNED16 =
{
  // Tetrahedral, <2, 3, 3>.
  {
    { { +0x1.000000P+0f, +0x0.000000P+0f, +0x0.000000P+0f, 0.0f, },
      { +0x1.279a74P-1f, +0x1.a20bd8P-1f, +0x0.000000P+0f, 0.0f, },
      { +0x1.279a74P-1f, +0x0.000000P+0f, +0x1.a20bd8P-1f, 0.0f, },
    },
    { { +0x1.000000P+0f, +0x0.000000P+0f, +0x0.000000P+0f, 0.0f, },
      { +0x0.000000P+0f, +0x1.000000P+0f, +0x0.000000P+0f, 0.0f, },
      { +0x0.000000P+0f, +0x0.000000P+0f, +0x1.000000P+0f, 0.0f, },
      { +0x0.000000P+0f, +0x1.3988e2P-1f, +0x1.3988e2P-1f, 0.0f, },
      { +0x1.34bf64P-1f, +0x0.000000P+0f, +0x1.0b621eP-1f, 0.0f, },
      { +0x1.34bf64P-1f, +0x1.0b621eP-1f, +0x0.000000P+0f, 0.0f, },
      { +0x1.c9f25cP-2f, +0x1.8c97f0P-2f, +0x1.8c97f0P-2f, 0.0f, },
      { +0x1.4cb7c0P-2f, +0x1.d2393eP-2f, +0x1.d2393eP-2f, 0.0f, }, // Icosahedron
      //{ -0x1.605a90P+0f, +0x1.792eceP-1f, +0x1.792eceP-1f, 0.0f, }, // Great icosahedron
    },
  },
  // Octahedral, <2, 4, 3>.
  // Aligned so that two octahedral triangles cover one tetrahedral triangle.
  {
    { { +0x1.6a09e6P-1f, +0x1.000000P-1f, +0x1.000000P-1f, 0.0f, },
      { +0x1.000000P+0f, +0x0.000000P+0f, +0x0.000000P+0f, 0.0f, },
      { +0x1.279a74P-1f, +0x1.a20bd8P-1f, +0x0.000000P+0f, 0.0f, },
    },
    { { +0x1.000000P+0f, +0x0.000000P+0f, +0x0.000000P+0f, 0.0f, },
      { +0x0.000000P+0f, +0x1.000000P+0f, +0x0.000000P+0f, 0.0f, },
      { +0x0.000000P+0f, +0x0.000000P+0f, +0x1.000000P+0f, 0.0f, },
      { +0x0.000000P+0f, +0x1.02ca46P-1f, +0x1.3cf3aeP-1f, 0.0f, },
      { +0x1.1fd4a6P-1f, +0x0.000000P+0f, +0x1.f28990P-2f, 0.0f, },
      { +0x1.43d136P-1f, +0x1.c9f25cP-2f, +0x0.000000P+0f, 0.0f, },
      { +0x1.b9d594P-2f, +0x1.386c8eP-2f, +0x1.7ea3c6P-2f, 0.0f, },
      { +0x1.31816eP-2f, +0x1.8d5502P-2f, +0x1.bdd092P-2f, 0.0f, },
    },
  },
  // Icosahedral, <2, 5, 3>.
  {
    { { +0x1.000000P+0f, +0x0.000000P+0f, +0x0.000000P+0f, 0.0f, },
      { +0x1.b38880P-1f, +0x1.0d2ca0P-1f, +0x0.000000P+0f, 0.0f, },
      { +0x1.de4bd6P-1f, +0x0.0000000P+0, +0x1.6d62c6P-2f, 0.0f, },
    },
    { { +0x1.000000P+0f, +0x0.000000P+0f, +0x0.000000P+0f, 0.0f, },
      { +0x0.000000P+0f, +0x1.000000P+0f, +0x0.000000P+0f, 0.0f, },
      { +0x0.000000P+0f, +0x0.000000P+0f, +0x1.000000P+0f, 0.0f, },
      { +0x0.000000P+0f, +0x1.b4242aP-2f, +0x1.414c80P-1f, 0.0f, },
      { +0x1.16fc4eP-1f, +0x0.000000P+0f, +0x1.e33798P-2f, 0.0f, },
      { +0x1.4e5014P-1f, +0x1.890220P-2f, +0x0.000000P+0f, 0.0f, },
      { +0x1.b3be36P-2f, +0x1.001f92P-2f, +0x1.795d50P-2f, 0.0f, },
      { +0x1.287f1eP-2f, +0x1.52a52eP-2f, +0x1.b882c6P-2f, 0.0f, },
    },
  }
};

// Turn a PQR triangle into a PRQ triangle.
void reflect (triangle_t & t)
{
  v4f x = load4f (t.xyz [0]);
  v4f y = load4f (t.xyz [1]);
  v4f z = load4f (t.xyz [2]);

  v4f n = normalize (cross (x, y));
  v4f d = dot (n, z) * n;

  store4f (t.xyz [1], z - (d + d));
  store4f (t.xyz [2], y);

  for (unsigned k = 0; k != 8; ++ k) {
    v4f a = load4f (t.abc [k]);
    store4f (t.abc [k], _mm_shuffle_ps (a, a, SHUFFLE (0, 2, 1, 3)));
  }
}

template <unsigned K>
ALWAYS_INLINE inline void copy (const float (* from) [4], float (& to) [K] [4])
{
  for (unsigned k = 0; k != K; ++ k) {
    store4f (to [k], load4f (from [k]));
  }
}

void initialize_systems (float (& abc) [system_count] [8] [4],
                         float (& xyz) [system_count] [3] [4],
                         float (& xyzinvt) [system_count] [3] [4],
                         unsigned (& primitive_count) [system_count],
                         unsigned (& vao_ids) [system_count])
{
  auto init = [&] (const triangle_t & t, system_select_t select, unsigned q, unsigned r) -> void
  {
    copy (t.xyz, xyz [select]);
    copy (t.abc, abc [select]);
    cramer::inverse_transpose (xyz [select], xyzinvt [select]);
    unsigned p = 2, N = 2 * p * q * r / (q * r + r * p + p * q - p * q * r);
    unsigned indices [60] [6];
    ALIGNED16 float nodes [62] [4];
    make_system (q, r, t.xyz, nodes, indices);
    vao_ids [select] = make_vao (N, nodes, indices);
    primitive_count [select] = N;
  };

  for (unsigned n = 0; n != 3; ++ n) {
    triangle_t & triangle = triangles [n];
    init (triangle, system_select_t (2 * n + 0), 3 + n, 3);
    reflect (triangle);
    init (triangle, system_select_t (2 * n + 1), 3, 3 + n);
  }
}
<|endoftext|>


<commit_before>#include "Navigation.h"
#include <iostream>
#include <assert.h>

using namespace std;

void testInputNodes(const char* file);
void testReconstructPath(const char* file);
void testFindPath(const char* file);
void testTravelFromSourceToSink(const char* file);

int main(int argc, char const *argv[])
{
	if(argc != 2)
	{
		cout << "usage:\n\t./a.out inputFileName" << endl;
		return 0;
	}

	system("clear");
	cout << "Running test on Navigation::inputNodes" << endl;
	testInputNodes(argv[1]);
	cout << "[PASS] Navigation::inputNodes" << endl << endl;
	cout << "Running test on Navigation::reconstructPath" << endl;
	testReconstructPath(argv[1]);
	cout << "[PASS] Navigation::reconstructPath" << endl << endl;
	testFindPath(argv[1]);
	cout << "Running test on Navigation::findPath" << endl;
	cout << "[PASS] Navigation::findPath" << endl << endl;
	testTravelFromSourceToSink(argv[1]);
	cout << "Running test on Navigation::travelFromSourceToSink" << endl;
	cout << "[PASS] Navigation::travelFromSourceToSink" << endl << endl;

	return 0;
}

void testInputNodes(const char* file)
{
	Navigation defaultNav;

	defaultNav.inputNodes(file);

	assert(defaultNav.getNode(0)->name=="node0");
	assert(defaultNav.getNode(0)->neighbors[0]->name=="node1");
	assert(defaultNav.getNode(0)->neighbors[1]->name=="node3");
	assert(defaultNav.getNode(0)->weights[0]==10);
	assert(defaultNav.getNode(0)->weights[1]==25);

	assert(defaultNav.getNode(1)->name=="node1");
	assert(defaultNav.getNode(1)->neighbors[0]->name=="node0");
	assert(defaultNav.getNode(1)->neighbors[1]->name=="node2");
	assert(defaultNav.getNode(1)->weights[0]==10);
	assert(defaultNav.getNode(1)->weights[1]==5);

	assert(defaultNav.getNode(2)->name=="node2");
	assert(defaultNav.getNode(2)->neighbors[0]->name=="node1");
	assert(defaultNav.getNode(2)->neighbors[1]->name=="node3");
	assert(defaultNav.getNode(2)->neighbors[2]->name=="node4");
	assert(defaultNav.getNode(2)->weights[0]==5);
	assert(defaultNav.getNode(2)->weights[1]==5);
	assert(defaultNav.getNode(2)->weights[2]==20);

	assert(defaultNav.getNode(3)->name=="node3");
	assert(defaultNav.getNode(3)->neighbors[0]->name=="node0");
	assert(defaultNav.getNode(3)->neighbors[1]->name=="node2");
	assert(defaultNav.getNode(3)->neighbors[2]->name=="node4");
	assert(defaultNav.getNode(3)->weights[0]==25);
	assert(defaultNav.getNode(3)->weights[1]==5);
	assert(defaultNav.getNode(3)->weights[2]==5);

	assert(defaultNav.getNode(4)->name=="node4");
	assert(defaultNav.getNode(4)->neighbors[0]->name=="node2");
	assert(defaultNav.getNode(4)->neighbors[1]->name=="node3");
	assert(defaultNav.getNode(4)->weights[0]==20);
	assert(defaultNav.getNode(4)->weights[1]==5);
}

void testReconstructPath(const char* file) {
	Navigation defaultNav;
	vector<Node*> path;

	defaultNav.inputNodes(file);

	defaultNav.getNode(4)->parent = defaultNav.getNode(3);
	defaultNav.getNode(3)->parent = defaultNav.getNode(2);
	defaultNav.getNode(2)->parent = defaultNav.getNode(1);
	defaultNav.getNode(1)->parent = defaultNav.getNode(0);
	defaultNav.getNode(0)->parent = NULL;

	path = defaultNav.dbgReconstructPath(defaultNav.getNode(4));

	assert(!path.empty());
	assert(path[0] == defaultNav.getNode(1));
	assert(path[1] == defaultNav.getNode(2));
	assert(path[2] == defaultNav.getNode(3));
	assert(path[3] == defaultNav.getNode(4));
}

void testFindPath(const char* file) {
	Navigation defaultNav;
	vector<Node*> path;

	defaultNav.inputNodes(file);
	path = defaultNav.dbgFindPath(defaultNav.getNode(0), defaultNav.getNode(4));

	assert(!path.empty());
	assert(path[0] == defaultNav.getNode(1));
	assert(path[1] == defaultNav.getNode(2));
	assert(path[2] == defaultNav.getNode(3));
	assert(path[3] == defaultNav.getNode(4));
}

void testTravelFromSourceToSink(const char* file) {
	Navigation defaultNav;
	bool arrived;

	defaultNav.inputNodes(file);

	arrived = defaultNav.travelFromSourceToSink(defaultNav.getNode(0), defaultNav.getNode(4));

	assert(arrived);
}<commit_msg>fuck your bracketing<commit_after>#include "Navigation.h"
#include <iostream>
#include <assert.h>

using namespace std;

void testInputNodes(const char* file);
void testReconstructPath(const char* file);
void testFindPath(const char* file);
void testTravelFromSourceToSink(const char* file);

int main(int argc, char const *argv[])
{
	if(argc != 2)
	{
		cout << "usage:\n\t./a.out inputFileName" << endl;
		return 0;
	}

	system("clear");
	cout << "Running test on Navigation::inputNodes" << endl;
	testInputNodes(argv[1]);
	cout << "[PASS] Navigation::inputNodes" << endl << endl;
	cout << "Running test on Navigation::reconstructPath" << endl;
	testReconstructPath(argv[1]);
	cout << "[PASS] Navigation::reconstructPath" << endl << endl;
	testFindPath(argv[1]);
	cout << "Running test on Navigation::findPath" << endl;
	cout << "[PASS] Navigation::findPath" << endl << endl;
	testTravelFromSourceToSink(argv[1]);
	cout << "Running test on Navigation::travelFromSourceToSink" << endl;
	cout << "[PASS] Navigation::travelFromSourceToSink" << endl << endl;

	return 0;
}

void testInputNodes(const char* file)
{
	Navigation defaultNav;

	defaultNav.inputNodes(file);

	assert(defaultNav.getNode(0)->name=="node0");
	assert(defaultNav.getNode(0)->neighbors[0]->name=="node1");
	assert(defaultNav.getNode(0)->neighbors[1]->name=="node3");
	assert(defaultNav.getNode(0)->weights[0]==10);
	assert(defaultNav.getNode(0)->weights[1]==25);

	assert(defaultNav.getNode(1)->name=="node1");
	assert(defaultNav.getNode(1)->neighbors[0]->name=="node0");
	assert(defaultNav.getNode(1)->neighbors[1]->name=="node2");
	assert(defaultNav.getNode(1)->weights[0]==10);
	assert(defaultNav.getNode(1)->weights[1]==5);

	assert(defaultNav.getNode(2)->name=="node2");
	assert(defaultNav.getNode(2)->neighbors[0]->name=="node1");
	assert(defaultNav.getNode(2)->neighbors[1]->name=="node3");
	assert(defaultNav.getNode(2)->neighbors[2]->name=="node4");
	assert(defaultNav.getNode(2)->weights[0]==5);
	assert(defaultNav.getNode(2)->weights[1]==5);
	assert(defaultNav.getNode(2)->weights[2]==20);

	assert(defaultNav.getNode(3)->name=="node3");
	assert(defaultNav.getNode(3)->neighbors[0]->name=="node0");
	assert(defaultNav.getNode(3)->neighbors[1]->name=="node2");
	assert(defaultNav.getNode(3)->neighbors[2]->name=="node4");
	assert(defaultNav.getNode(3)->weights[0]==25);
	assert(defaultNav.getNode(3)->weights[1]==5);
	assert(defaultNav.getNode(3)->weights[2]==5);

	assert(defaultNav.getNode(4)->name=="node4");
	assert(defaultNav.getNode(4)->neighbors[0]->name=="node2");
	assert(defaultNav.getNode(4)->neighbors[1]->name=="node3");
	assert(defaultNav.getNode(4)->weights[0]==20);
	assert(defaultNav.getNode(4)->weights[1]==5);
}

void testReconstructPath(const char* file)
{
	Navigation defaultNav;
	vector<Node*> path;

	defaultNav.inputNodes(file);

	defaultNav.getNode(4)->parent = defaultNav.getNode(3);
	defaultNav.getNode(3)->parent = defaultNav.getNode(2);
	defaultNav.getNode(2)->parent = defaultNav.getNode(1);
	defaultNav.getNode(1)->parent = defaultNav.getNode(0);
	defaultNav.getNode(0)->parent = NULL;

	path = defaultNav.dbgReconstructPath(defaultNav.getNode(4));

	assert(!path.empty());
	assert(path[0] == defaultNav.getNode(1));
	assert(path[1] == defaultNav.getNode(2));
	assert(path[2] == defaultNav.getNode(3));
	assert(path[3] == defaultNav.getNode(4));
}

void testFindPath(const char* file)
{
	Navigation defaultNav;
	vector<Node*> path;

	defaultNav.inputNodes(file);
	path = defaultNav.dbgFindPath(defaultNav.getNode(0), defaultNav.getNode(4));

	assert(!path.empty());
	assert(path[0] == defaultNav.getNode(1));
	assert(path[1] == defaultNav.getNode(2));
	assert(path[2] == defaultNav.getNode(3));
	assert(path[3] == defaultNav.getNode(4));
}

void testTravelFromSourceToSink(const char* file)
{
	Navigation defaultNav;
	bool arrived;

	defaultNav.inputNodes(file);

	arrived = defaultNav.travelFromSourceToSink(defaultNav.getNode(0), defaultNav.getNode(4));

	assert(arrived);
}<|endoftext|>


<commit_before>/* -------------------------------------------------------------------------- *
 *                          OpenSim:  RootSolver.cpp                          *
 * -------------------------------------------------------------------------- *
 * The OpenSim API is a toolkit for musculoskeletal modeling and simulation.  *
 * See http://opensim.stanford.edu and the NOTICE file for more information.  *
 * OpenSim is developed at Stanford University and supported by the US        *
 * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA    *
 * through the Warrior Web program.                                           *
 *                                                                            *
 * Copyright (c) 2005-2012 Stanford University and the Authors                *
 * Author(s): Frank C. Anderson                                               *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
 * not use this file except in compliance with the License. You may obtain a  *
 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 * -------------------------------------------------------------------------- */

/*
 * Author: Frank C. Anderson
 */

// INCLUDES
#include <iostream>
#include <string>
#include <float.h>
#include <math.h>
#include "RootSolver.h"

using namespace OpenSim;
using namespace std;

//=============================================================================
// DESTRUCTOR AND CONSTRUCTORS
//=============================================================================
//_____________________________________________________________________________
/**
 * Destructor.
 */
RootSolver::~RootSolver()
{
}

//_____________________________________________________________________________
/**
 * Default constructor.
 */
RootSolver::
RootSolver(VectorFunctionUncoupledNxN *aFunc)
{
	setNull();
	_function = aFunc;
}

//-----------------------------------------------------------------------------
// CONSTRUCTION METHODS
//-----------------------------------------------------------------------------
//_____________________________________________________________________________
/**
 * Set all member variables to NULL values.
 */
void RootSolver::
setNull()
{
	_function = NULL;
}

//=============================================================================
// SOLVE
//=============================================================================
//_____________________________________________________________________________
/**
 * Solve for the roots.
 *
 *
 */
Array<double> RootSolver::
solve(const SimTK::State& s, const Array<double> &ax,const Array<double> &bx,
		const Array<double> &tol)
{
	int i;
	int N = _function->getNX();

	Array<double> a(0.0,N),b(0.0,N),c(0.0,N);
	Array<double> fa(0.0,N),fb(0.0,N),fc(0.0,N);
	Array<double> prev_step(0.0,N);
	Array<double> tol_act(0.0,N);
	Array<double> p(0.0,N);
	Array<double> q(0.0,N);
	Array<double> new_step(0.0,N);

	bool finished = false;
	Array<int>   converged(0,N);

	// INITIALIZATIONS
	a = ax;
	b = bx;
	_function->evaluate(s,a,fa);
	_function->evaluate(s,b,fb);
	c = a;
	fc = fa;

	// ITERATION LOOP
	int iter;
	for(iter=0;!finished;iter++) {

		// ABSCISSAE MANIPULATION LOOP
		for(i=0;i<N;i++) {

			// Continue?
			// If a function is already converged no need to do any manipulation.
			if(converged[i]) continue;

			// Make c on opposite side of b.
			// (was down at very bottom)
			 if( (fb[i]>0.0 && fc[i]>0.0) || (fb[i]<0.0 && fc[i]<0.0) ) {
				c[i] = a[i];
				fc[i] = fa[i];
			 }

			// Record previous step
			prev_step[i] = b[i] - a[i];

			// Swap data for b to be the best approximation.
			if( fabs(fc[i]) < fabs(fb[i]) ) {
				a[i] = b[i];  b[i] = c[i];  c[i] = a[i];
				fa[i]= fb[i]; fb[i]= fc[i]; fc[i]= fa[i];
			}
			tol_act[i] = 2.0*DBL_EPSILON*fabs(b[i]) + 0.5*tol[i];
			new_step[i] = 0.5 * (c[i]-b[i]);

			// Converged?
			// Original convergence test:
			if(fabs(new_step[i])<=tol_act[i] || fb[i]==(double)0.0 ) {
				converged[i] = iter;
				continue;
			}

			// Interpolate if prev_step was large enough and in true direction
			if( fabs(prev_step[i])>=tol_act[i] && fabs(fa[i])>fabs(fb[i]) ) {
				register double t1,cb,t2;
				cb = c[i]-b[i];

				// Only two distinct roots, must use linear interpolation.
				if(a[i]==c[i]) {
					t1 = fb[i]/fa[i];
					p[i] = cb*t1;
					q[i] = 1.0 - t1;

				// Quadratic interpolation
				} else {
					q[i] = fa[i]/fc[i];  t1 = fb[i]/fc[i];  t2 = fb[i]/fa[i];
					p[i] = t2 * ( cb*q[i]*(q[i]-t1) - (b[i]-a[i])*(t1-1.0) );
					q[i] = (q[i]-1.0) * (t1-1.0) * (t2-1.0);
				}

				// Change sign of q or p?
				if( p[i]>(double)0.0 ) {
					q[i] = -q[i];
				} else {
					p[i] = -p[i];
				}

				// If the interpolate is bad, use bissection.
				if( p[i]<(0.75*cb*q[i] - 0.5*fabs(tol_act[i]*q[i]))	&& p[i]<fabs(0.5*prev_step[i]*q[i]) )
					new_step[i] = p[i]/q[i];
			}

			// Adjust step to be not less than tolerance.
			if( fabs(new_step[i]) < tol_act[i] )
				if( new_step[i] > (double)0.0 )
					new_step[i] = tol_act[i];
				else
					new_step[i] = -tol_act[i];

			// Save previous approximation.
			a[i] = b[i];  fa[i] = fb[i];

			b[i] += new_step[i];

		} // END ABSCISSAE LOOP

		// NEW FUNCTION EVALUATION
		_function->evaluate(s, b,fb);

		// FINISHED?
		for(i=0;i<N;i++) {
			finished = true;
			if(!converged[i]) {
				finished = false;
				break;
			}
		}
	}

	// PRINT
	//cout<<"\n\nRootSolver:  found solution in "<<iter<<" iterations.\n";
	//cout<<"converged array:\n";
	//cout<<converged<<endl<<endl;
	//cout<<"roots:\n";
	//cout<<b<<endl<<endl;
	//cout<<"errors:\n";
	//cout<<fb<<endl;

	return(b);
}
<commit_msg>Address Clang warning about ambiguous nested 'else' clause.<commit_after>/* -------------------------------------------------------------------------- *
 *                          OpenSim:  RootSolver.cpp                          *
 * -------------------------------------------------------------------------- *
 * The OpenSim API is a toolkit for musculoskeletal modeling and simulation.  *
 * See http://opensim.stanford.edu and the NOTICE file for more information.  *
 * OpenSim is developed at Stanford University and supported by the US        *
 * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA    *
 * through the Warrior Web program.                                           *
 *                                                                            *
 * Copyright (c) 2005-2012 Stanford University and the Authors                *
 * Author(s): Frank C. Anderson                                               *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
 * not use this file except in compliance with the License. You may obtain a  *
 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 * -------------------------------------------------------------------------- */

/*
 * Author: Frank C. Anderson
 */

// INCLUDES
#include <iostream>
#include <string>
#include <float.h>
#include <math.h>
#include "RootSolver.h"

using namespace OpenSim;
using namespace std;

//=============================================================================
// DESTRUCTOR AND CONSTRUCTORS
//=============================================================================
//_____________________________________________________________________________
/**
 * Destructor.
 */
RootSolver::~RootSolver()
{
}

//_____________________________________________________________________________
/**
 * Default constructor.
 */
RootSolver::
RootSolver(VectorFunctionUncoupledNxN *aFunc)
{
	setNull();
	_function = aFunc;
}

//-----------------------------------------------------------------------------
// CONSTRUCTION METHODS
//-----------------------------------------------------------------------------
//_____________________________________________________________________________
/**
 * Set all member variables to NULL values.
 */
void RootSolver::
setNull()
{
	_function = NULL;
}

//=============================================================================
// SOLVE
//=============================================================================
//_____________________________________________________________________________
/**
 * Solve for the roots.
 *
 *
 */
Array<double> RootSolver::
solve(const SimTK::State& s, const Array<double> &ax,const Array<double> &bx,
		const Array<double> &tol)
{
	int i;
	int N = _function->getNX();

	Array<double> a(0.0,N),b(0.0,N),c(0.0,N);
	Array<double> fa(0.0,N),fb(0.0,N),fc(0.0,N);
	Array<double> prev_step(0.0,N);
	Array<double> tol_act(0.0,N);
	Array<double> p(0.0,N);
	Array<double> q(0.0,N);
	Array<double> new_step(0.0,N);

	bool finished = false;
	Array<int>   converged(0,N);

	// INITIALIZATIONS
	a = ax;
	b = bx;
	_function->evaluate(s,a,fa);
	_function->evaluate(s,b,fb);
	c = a;
	fc = fa;

	// ITERATION LOOP
	int iter;
	for(iter=0;!finished;iter++) {

		// ABSCISSAE MANIPULATION LOOP
		for(i=0;i<N;i++) {

			// Continue?
			// If a function is already converged no need to do any manipulation.
			if(converged[i]) continue;

			// Make c on opposite side of b.
			// (was down at very bottom)
			 if( (fb[i]>0.0 && fc[i]>0.0) || (fb[i]<0.0 && fc[i]<0.0) ) {
				c[i] = a[i];
				fc[i] = fa[i];
			 }

			// Record previous step
			prev_step[i] = b[i] - a[i];

			// Swap data for b to be the best approximation.
			if( fabs(fc[i]) < fabs(fb[i]) ) {
				a[i] = b[i];  b[i] = c[i];  c[i] = a[i];
				fa[i]= fb[i]; fb[i]= fc[i]; fc[i]= fa[i];
			}
			tol_act[i] = 2.0*DBL_EPSILON*fabs(b[i]) + 0.5*tol[i];
			new_step[i] = 0.5 * (c[i]-b[i]);

			// Converged?
			// Original convergence test:
			if(fabs(new_step[i])<=tol_act[i] || fb[i]==(double)0.0 ) {
				converged[i] = iter;
				continue;
			}

			// Interpolate if prev_step was large enough and in true direction
			if( fabs(prev_step[i])>=tol_act[i] && fabs(fa[i])>fabs(fb[i]) ) {
				register double t1,cb,t2;
				cb = c[i]-b[i];

				// Only two distinct roots, must use linear interpolation.
				if(a[i]==c[i]) {
					t1 = fb[i]/fa[i];
					p[i] = cb*t1;
					q[i] = 1.0 - t1;

				// Quadratic interpolation
				} else {
					q[i] = fa[i]/fc[i];  t1 = fb[i]/fc[i];  t2 = fb[i]/fa[i];
					p[i] = t2 * ( cb*q[i]*(q[i]-t1) - (b[i]-a[i])*(t1-1.0) );
					q[i] = (q[i]-1.0) * (t1-1.0) * (t2-1.0);
				}

				// Change sign of q or p?
				if( p[i]>(double)0.0 ) {
					q[i] = -q[i];
				} else {
					p[i] = -p[i];
				}

				// If the interpolate is bad, use bissection.
				if( p[i]<(0.75*cb*q[i] - 0.5*fabs(tol_act[i]*q[i]))	&& p[i]<fabs(0.5*prev_step[i]*q[i]) )
					new_step[i] = p[i]/q[i];
			}

			// Adjust step to be not less than tolerance.
			if( fabs(new_step[i]) < tol_act[i] ) {
				if( new_step[i] > (double)0.0 ) {
					new_step[i] = tol_act[i];
                }
				else {
					new_step[i] = -tol_act[i];
                }
            }

			// Save previous approximation.
			a[i] = b[i];  fa[i] = fb[i];

			b[i] += new_step[i];

		} // END ABSCISSAE LOOP

		// NEW FUNCTION EVALUATION
		_function->evaluate(s, b,fb);

		// FINISHED?
		for(i=0;i<N;i++) {
			finished = true;
			if(!converged[i]) {
				finished = false;
				break;
			}
		}
	}

	// PRINT
	//cout<<"\n\nRootSolver:  found solution in "<<iter<<" iterations.\n";
	//cout<<"converged array:\n";
	//cout<<converged<<endl<<endl;
	//cout<<"roots:\n";
	//cout<<b<<endl<<endl;
	//cout<<"errors:\n";
	//cout<<fb<<endl;

	return(b);
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////

#include <cmake.h>
#include <Context.h>
#include <Msg.h>
#include <test.h>

Context context;

////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{
  UnitTest t (12);

  Msg m;
  t.is (m.serialize (), std::string ("client: ") + PACKAGE_STRING + "\n\n\n", "Msg::serialize '' --> '\\n\\n'");

  m.set ("name", "value");
  t.is (m.serialize (), std::string ("client: ") + PACKAGE_STRING + "\nname: value\n\n\n", "Msg::serialize 1 var");

  m.set ("foo", "bar");
  t.is (m.serialize (), std::string ("client: ") + PACKAGE_STRING + "\nfoo: bar\nname: value\n\n\n", "Msg::serialize 2 vars");

  m.setPayload ("payload");
  t.is (m.serialize (), std::string ("client: ") + PACKAGE_STRING + "\nfoo: bar\nname: value\n\npayload\n", "Msg::serialize 2 vars + payload");

  Msg m2;
  t.ok (m2.parse ("foo: bar\nname: value\n\npayload\n"),  "Msg::parse ok");
  t.is (m2.get ("foo"),   "bar",                          "Msg::get");
  t.is (m2.get ("name"),  "value",                        "Msg::get");
  t.is (m2.getPayload (), "payload\n",                    "Msg::getPayload");

  Msg m3;
  t.ok (m3.parse ("foo:bar\nname:   value\n\npayload\n"), "Msg::parse ok");
  t.is (m3.get ("foo"),   "bar",                          "Msg::get");
  t.is (m3.get ("name"),  "value",                        "Msg::get");
  t.is (m3.getPayload (), "payload\n",                    "Msg::getPayload");

  return 0;
}

////////////////////////////////////////////////////////////////////////////////
<commit_msg>Test: Added test for Msg::all<commit_after>////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////

#include <cmake.h>
#include <Context.h>
#include <Msg.h>
#include <test.h>

Context context;

////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{
  UnitTest t (13);

  Msg m;
  t.is (m.serialize (), std::string ("client: ") + PACKAGE_STRING + "\n\n\n", "Msg::serialize '' --> '\\n\\n'");

  m.set ("name", "value");
  t.is (m.serialize (), std::string ("client: ") + PACKAGE_STRING + "\nname: value\n\n\n", "Msg::serialize 1 var");

  m.set ("foo", "bar");
  t.is (m.serialize (), std::string ("client: ") + PACKAGE_STRING + "\nfoo: bar\nname: value\n\n\n", "Msg::serialize 2 vars");

  m.setPayload ("payload");
  t.is (m.serialize (), std::string ("client: ") + PACKAGE_STRING + "\nfoo: bar\nname: value\n\npayload\n", "Msg::serialize 2 vars + payload");

  Msg m2;
  t.ok (m2.parse ("foo: bar\nname: value\n\npayload\n"),  "Msg::parse ok");
  t.is (m2.get ("foo"),   "bar",                          "Msg::get");
  t.is (m2.get ("name"),  "value",                        "Msg::get");
  t.is (m2.getPayload (), "payload\n",                    "Msg::getPayload");

  Msg m3;
  t.ok (m3.parse ("foo:bar\nname:   value\n\npayload\n"), "Msg::parse ok");
  t.is (m3.get ("foo"),   "bar",                          "Msg::get");
  t.is (m3.get ("name"),  "value",                        "Msg::get");
  t.is (m3.getPayload (), "payload\n",                    "Msg::getPayload");

  std::vector <std::string> vars;
  m3.all (vars);
  t.ok (vars.size () == 2,                                "Msg::all --> 2 vars");

  return 0;
}

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


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// Eigen is free software; you can 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 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#include "main.h"

template<typename MatrixType> void matrixRedux(const MatrixType& m)
{
  typedef typename MatrixType::Scalar Scalar;

  int rows = m.rows();
  int cols = m.cols();

  MatrixType m1 = MatrixType::Random(rows, cols);

  VERIFY_IS_MUCH_SMALLER_THAN(MatrixType::Zero(rows, cols).sum(), Scalar(1));
  VERIFY_IS_APPROX(MatrixType::Ones(rows, cols).sum(), Scalar(float(rows*cols))); // the float() here to shut up excessive MSVC warning about int->complex conversion being lossy
  Scalar s(0), p(1), minc(ei_real(m1.coeff(0))), maxc(ei_real(m1.coeff(0)));
  for(int j = 0; j < cols; j++)
  for(int i = 0; i < rows; i++)
  {
    s += m1(i,j);
    p *= m1(i,j);
    minc = std::min(ei_real(minc), ei_real(m1(i,j)));
    maxc = std::max(ei_real(maxc), ei_real(m1(i,j)));
  }
  const Scalar mean = s/Scalar(rows*cols);
  const Scalar other_mean = m1.mean();

  VERIFY_IS_APPROX(m1.sum(), s);
  VERIFY_IS_APPROX(m1.mean(), mean);
  VERIFY_IS_APPROX(m1.prod(), p);
  VERIFY_IS_APPROX(m1.real().minCoeff(), ei_real(minc));
  VERIFY_IS_APPROX(m1.real().maxCoeff(), ei_real(maxc));
}

template<typename VectorType> void vectorRedux(const VectorType& w)
{
  typedef typename VectorType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  int size = w.size();

  VectorType v = VectorType::Random(size);
  for(int i = 1; i < size; i++)
  {
    Scalar s(0), p(1);
    RealScalar minc(ei_real(v.coeff(0))), maxc(ei_real(v.coeff(0)));
    for(int j = 0; j < i; j++)
    {
      s += v[j];
      p *= v[j];
      minc = std::min(minc, ei_real(v[j]));
      maxc = std::max(maxc, ei_real(v[j]));
    }
    VERIFY_IS_APPROX(s, v.head(i).sum());
    VERIFY_IS_APPROX(p, v.head(i).prod());
    VERIFY_IS_APPROX(minc, v.real().head(i).minCoeff());
    VERIFY_IS_APPROX(maxc, v.real().head(i).maxCoeff());
  }

  for(int i = 0; i < size-1; i++)
  {
    Scalar s(0), p(1);
    RealScalar minc(ei_real(v.coeff(i))), maxc(ei_real(v.coeff(i)));
    for(int j = i; j < size; j++)
    {
      s += v[j];
      p *= v[j];
      minc = std::min(minc, ei_real(v[j]));
      maxc = std::max(maxc, ei_real(v[j]));
    }
    VERIFY_IS_APPROX(s, v.tail(size-i).sum());
    VERIFY_IS_APPROX(p, v.tail(size-i).prod());
    VERIFY_IS_APPROX(minc, v.real().tail(size-i).minCoeff());
    VERIFY_IS_APPROX(maxc, v.real().tail(size-i).maxCoeff());
  }

  for(int i = 0; i < size/2; i++)
  {
    Scalar s(0), p(1);
    RealScalar minc(ei_real(v.coeff(i))), maxc(ei_real(v.coeff(i)));
    for(int j = i; j < size-i; j++)
    {
      s += v[j];
      p *= v[j];
      minc = std::min(minc, ei_real(v[j]));
      maxc = std::max(maxc, ei_real(v[j]));
    }
    VERIFY_IS_APPROX(s, v.segment(i, size-2*i).sum());
    VERIFY_IS_APPROX(p, v.segment(i, size-2*i).prod());
    VERIFY_IS_APPROX(minc, v.real().segment(i, size-2*i).minCoeff());
    VERIFY_IS_APPROX(maxc, v.real().segment(i, size-2*i).maxCoeff());
  }
}

void test_redux()
{
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1( matrixRedux(Matrix<float, 1, 1>()) );
    CALL_SUBTEST_1( matrixRedux(Array<float, 1, 1>()) );
    CALL_SUBTEST_2( matrixRedux(Matrix2f()) );
    CALL_SUBTEST_2( matrixRedux(Array2f()) );
    CALL_SUBTEST_3( matrixRedux(Matrix4d()) );
    CALL_SUBTEST_3( matrixRedux(Array4d()) );
    CALL_SUBTEST_4( matrixRedux(MatrixXcf(3, 3)) );
    CALL_SUBTEST_4( matrixRedux(ArrayXXcf(3, 3)) );
    CALL_SUBTEST_5( matrixRedux(MatrixXd(8, 12)) );
    CALL_SUBTEST_5( matrixRedux(ArrayXXd(8, 12)) );
    CALL_SUBTEST_6( matrixRedux(MatrixXi(8, 12)) );
    CALL_SUBTEST_6( matrixRedux(ArrayXXi(8, 12)) );
  }
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_7( vectorRedux(Vector4f()) );
    CALL_SUBTEST_7( vectorRedux(Array4f()) );
    CALL_SUBTEST_5( vectorRedux(VectorXd(10)) );
    CALL_SUBTEST_5( vectorRedux(ArrayXd(10)) );
    CALL_SUBTEST_8( vectorRedux(VectorXf(33)) );
    CALL_SUBTEST_8( vectorRedux(ArrayXf(33)) );
  }
}
<commit_msg>One warning less...<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// Eigen is free software; you can 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 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#include "main.h"

template<typename MatrixType> void matrixRedux(const MatrixType& m)
{
  typedef typename MatrixType::Scalar Scalar;

  int rows = m.rows();
  int cols = m.cols();

  MatrixType m1 = MatrixType::Random(rows, cols);

  VERIFY_IS_MUCH_SMALLER_THAN(MatrixType::Zero(rows, cols).sum(), Scalar(1));
  VERIFY_IS_APPROX(MatrixType::Ones(rows, cols).sum(), Scalar(float(rows*cols))); // the float() here to shut up excessive MSVC warning about int->complex conversion being lossy
  Scalar s(0), p(1), minc(ei_real(m1.coeff(0))), maxc(ei_real(m1.coeff(0)));
  for(int j = 0; j < cols; j++)
  for(int i = 0; i < rows; i++)
  {
    s += m1(i,j);
    p *= m1(i,j);
    minc = std::min(ei_real(minc), ei_real(m1(i,j)));
    maxc = std::max(ei_real(maxc), ei_real(m1(i,j)));
  }
  const Scalar mean = s/Scalar(rows*cols);

  VERIFY_IS_APPROX(m1.sum(), s);
  VERIFY_IS_APPROX(m1.mean(), mean);
  VERIFY_IS_APPROX(m1.prod(), p);
  VERIFY_IS_APPROX(m1.real().minCoeff(), ei_real(minc));
  VERIFY_IS_APPROX(m1.real().maxCoeff(), ei_real(maxc));
}

template<typename VectorType> void vectorRedux(const VectorType& w)
{
  typedef typename VectorType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  int size = w.size();

  VectorType v = VectorType::Random(size);
  for(int i = 1; i < size; i++)
  {
    Scalar s(0), p(1);
    RealScalar minc(ei_real(v.coeff(0))), maxc(ei_real(v.coeff(0)));
    for(int j = 0; j < i; j++)
    {
      s += v[j];
      p *= v[j];
      minc = std::min(minc, ei_real(v[j]));
      maxc = std::max(maxc, ei_real(v[j]));
    }
    VERIFY_IS_APPROX(s, v.head(i).sum());
    VERIFY_IS_APPROX(p, v.head(i).prod());
    VERIFY_IS_APPROX(minc, v.real().head(i).minCoeff());
    VERIFY_IS_APPROX(maxc, v.real().head(i).maxCoeff());
  }

  for(int i = 0; i < size-1; i++)
  {
    Scalar s(0), p(1);
    RealScalar minc(ei_real(v.coeff(i))), maxc(ei_real(v.coeff(i)));
    for(int j = i; j < size; j++)
    {
      s += v[j];
      p *= v[j];
      minc = std::min(minc, ei_real(v[j]));
      maxc = std::max(maxc, ei_real(v[j]));
    }
    VERIFY_IS_APPROX(s, v.tail(size-i).sum());
    VERIFY_IS_APPROX(p, v.tail(size-i).prod());
    VERIFY_IS_APPROX(minc, v.real().tail(size-i).minCoeff());
    VERIFY_IS_APPROX(maxc, v.real().tail(size-i).maxCoeff());
  }

  for(int i = 0; i < size/2; i++)
  {
    Scalar s(0), p(1);
    RealScalar minc(ei_real(v.coeff(i))), maxc(ei_real(v.coeff(i)));
    for(int j = i; j < size-i; j++)
    {
      s += v[j];
      p *= v[j];
      minc = std::min(minc, ei_real(v[j]));
      maxc = std::max(maxc, ei_real(v[j]));
    }
    VERIFY_IS_APPROX(s, v.segment(i, size-2*i).sum());
    VERIFY_IS_APPROX(p, v.segment(i, size-2*i).prod());
    VERIFY_IS_APPROX(minc, v.real().segment(i, size-2*i).minCoeff());
    VERIFY_IS_APPROX(maxc, v.real().segment(i, size-2*i).maxCoeff());
  }
}

void test_redux()
{
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1( matrixRedux(Matrix<float, 1, 1>()) );
    CALL_SUBTEST_1( matrixRedux(Array<float, 1, 1>()) );
    CALL_SUBTEST_2( matrixRedux(Matrix2f()) );
    CALL_SUBTEST_2( matrixRedux(Array2f()) );
    CALL_SUBTEST_3( matrixRedux(Matrix4d()) );
    CALL_SUBTEST_3( matrixRedux(Array4d()) );
    CALL_SUBTEST_4( matrixRedux(MatrixXcf(3, 3)) );
    CALL_SUBTEST_4( matrixRedux(ArrayXXcf(3, 3)) );
    CALL_SUBTEST_5( matrixRedux(MatrixXd(8, 12)) );
    CALL_SUBTEST_5( matrixRedux(ArrayXXd(8, 12)) );
    CALL_SUBTEST_6( matrixRedux(MatrixXi(8, 12)) );
    CALL_SUBTEST_6( matrixRedux(ArrayXXi(8, 12)) );
  }
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_7( vectorRedux(Vector4f()) );
    CALL_SUBTEST_7( vectorRedux(Array4f()) );
    CALL_SUBTEST_5( vectorRedux(VectorXd(10)) );
    CALL_SUBTEST_5( vectorRedux(ArrayXd(10)) );
    CALL_SUBTEST_8( vectorRedux(VectorXf(33)) );
    CALL_SUBTEST_8( vectorRedux(ArrayXf(33)) );
  }
}
<|endoftext|>


<commit_before>#include "trainer.hpp" //trainer class

void Trainer::SetLife(float life) //setlife function
{
  //write process memory with the new value
	int stat = WriteProcessMemory(Trainer::memory.hProc, (LPVOID)Trainer::TRAINER_LIFE, &life, (DWORD)sizeof(life), NULL);

	if (stat > 0){ //if it success it says this
		std::clog << "Sucesso ao escrever na memoria com valor: " << life << std::endl;
	}
	else { //if not it says another thing
		std::cerr << "Ocorreu algo inesperado, tente novamente." << std::endl;
	}
}

//same thing as life
void Trainer::SetMoney(int money)
{
	int stat = WriteProcessMemory(Trainer::memory.hProc, (LPVOID)Trainer::TRAINER_MONEY, &money, (DWORD)sizeof(money), NULL);

	if (stat > 0){
		std::clog << "Sucesso ao escrever na memoria com valor: " << money << std::endl;
	}
	else {
		std::cerr << "Ocorreu algo inesperado, tente novamente." << std::endl;
	}
}

//Entries: Red, Green, Blue, Alpha.
//Changes the color of health bar
void Trainer::SetHealthBarColor(int R, int G, int B, int A)
{
	if (WriteProcessMemory(Trainer::memory.hProc, (LPVOID)Trainer::TRAINER_RED, &R, sizeof(R), NULL))
	if (WriteProcessMemory(Trainer::memory.hProc, (LPVOID)Trainer::TRAINER_GREEN, &G, sizeof(G), NULL))
	if (WriteProcessMemory(Trainer::memory.hProc, (LPVOID)Trainer::TRAINER_BLUE, &B, sizeof(B), NULL))
	if (WriteProcessMemory(Trainer::memory.hProc, (LPVOID)Trainer::TRAINER_ALPHA, &A, sizeof(A), NULL))

	//it will write all the memories, if the previously won't return an error value.
}

//this one is diferent it has dynamic address, i did this way but i will probably use another way so i don't have to create
//multiple variables to declare each dynamic addres
void Trainer::SetArmor(float armor)
{
	unsigned long pointer = 0xB6F5F0; //CPed address
	unsigned long offset = 0x548; //armor address
	unsigned long address = pointer + offset; //the address's combined togther

	//same thing as the life, it writes a new value to the memory
	int stat = WriteProcessMemory(Trainer::memory.hProc, (LPVOID)address, &armor, (DWORD)sizeof(armor), NULL);

	if (stat > 0){
		std::clog << "Sucesso ao escrever na memoria com valor: " << armor << std::endl;
	}
	else {
		std::cerr << "Ocorreu algo inesperado, tente novamente." << std::endl;
	}
}
void Trainer::SetWantedLevel(int level)
{
	int stat = WriteProcessMemory(Trainer::memory.hProc, (LPVOID)Trainer::TRAINER_WANTED, &level, (DWORD)sizeof(level), NULL);

	if (stat > 0){
		std::clog << "Sucesso ao escrever na memoria com valor: " << level << std::endl;
	}
	else {
		std::cerr << "Ocorreu algo inesperado, tente novamente." << std::endl;
	}

}

/* Future functions
void Trainer::SetX(double pos)
{
	int stat = WriteProcessMemory(Trainer::memory.hProc, (LPVOID)Trainer::TRAINER_X, &pos, (DWORD)sizeof(pos), NULL);

	if (stat > 0){
		std::clog << "Sucesso ao escrever na memoria com valor: " << pos << std::endl;
	}
	else {
		std::cerr << "Ocorreu algo inesperado, tente novamente." << std::endl;
	}
}

void Trainer::SetY(double pos)
{
	int stat = WriteProcessMemory(Trainer::memory.hProc, (LPVOID)Trainer::TRAINER_Y, &pos, (DWORD)sizeof(pos), NULL);

	if (stat > 0){
		std::clog << "Sucesso ao escrever na memoria com valor: " << pos << std::endl;
	}
	else {
		std::cerr << "Ocorreu algo inesperado, tente novamente." << std::endl;
	}
}

void Trainer::SetZ(double pos)
{
	int stat = WriteProcessMemory(Trainer::memory.hProc, (LPVOID)Trainer::TRAINER_Z, &pos, (DWORD)sizeof(pos), NULL);

	if (stat > 0){
		std::clog << "Sucesso ao escrever na memoria com valor: " << pos << std::endl;
	}
	else {
		std::cerr << "Ocorreu algo inesperado, tente novamente." << std::endl;
	}
}

void Trainer::SetPos(double x,double y, double z)
{
	Trainer::SetX(x); Trainer::SetY(y); Trainer::SetZ(z);
}*/
<commit_msg>Removed useless instructions<commit_after>#include "trainer.hpp" //trainer class

void Trainer::SetLife(float life) //setlife function
{
  	//write process memory with the new value
	int stat = WriteProcessMemory(Trainer::memory.hProc, (LPVOID)Trainer::TRAINER_LIFE, &life, (DWORD)sizeof(life), NULL);

	if (stat <= 0){ //if it success it says this
		std::cerr << "Ocorreu algo inesperado, tente novamente." << std::endl;
		return;
	}
	std::clog << "Sucesso ao escrever na memoria com valor: " << life << std::endl;
}

//same thing as life
void Trainer::SetMoney(int money)
{
	int stat = WriteProcessMemory(Trainer::memory.hProc, (LPVOID)Trainer::TRAINER_MONEY, &money, (DWORD)sizeof(money), NULL);

	if (stat <= 0){
		std::cerr << "Ocorreu algo inesperado, tente novamente." << std::endl;
		return;
	}
	std::clog << "Sucesso ao escrever na memoria com valor: " << money << std::endl;
}

//Entries: Red, Green, Blue, Alpha.
//Changes the color of health bar
void Trainer::SetHealthBarColor(int R, int G, int B, int A)
{
	if (WriteProcessMemory(Trainer::memory.hProc, (LPVOID)Trainer::TRAINER_RED, &R, sizeof(R), NULL))
	if (WriteProcessMemory(Trainer::memory.hProc, (LPVOID)Trainer::TRAINER_GREEN, &G, sizeof(G), NULL))
	if (WriteProcessMemory(Trainer::memory.hProc, (LPVOID)Trainer::TRAINER_BLUE, &B, sizeof(B), NULL))
	if (WriteProcessMemory(Trainer::memory.hProc, (LPVOID)Trainer::TRAINER_ALPHA, &A, sizeof(A), NULL))

	//it will write all the memories, if the previously won't return an error value.
}

//this one is diferent it has dynamic address, i did this way but i will probably use another way so i don't have to create
//multiple variables to declare each dynamic addres
void Trainer::SetArmor(float armor)
{
	unsigned long pointer = 0xB6F5F0; //CPed address
	unsigned long offset = 0x548; //armor address
	unsigned long address = pointer + offset; //the address's combined togther

	//same thing as the life, it writes a new value to the memory
	int stat = WriteProcessMemory(Trainer::memory.hProc, (LPVOID)address, &armor, (DWORD)sizeof(armor), NULL);

	if (stat <= 0){
		std::cerr << "Ocorreu algo inesperado, tente novamente." << std::endl;
		return;
	}

	std::clog << "Sucesso ao escrever na memoria com valor: " << armor << std::endl;
}
void Trainer::SetWantedLevel(int level)
{
	int stat = WriteProcessMemory(Trainer::memory.hProc, (LPVOID)Trainer::TRAINER_WANTED, &level, (DWORD)sizeof(level), NULL);

	if (stat <= 0){
		std::cerr << "Ocorreu algo inesperado, tente novamente." << std::endl;
		return;
	}

	std::clog << "Sucesso ao escrever na memoria com valor: " << level << std::endl;
}

/* Future functions
void Trainer::SetX(double pos)
{
	int stat = WriteProcessMemory(Trainer::memory.hProc, (LPVOID)Trainer::TRAINER_X, &pos, (DWORD)sizeof(pos), NULL);

	if (stat > 0){
		std::clog << "Sucesso ao escrever na memoria com valor: " << pos << std::endl;
	}
	else {
		std::cerr << "Ocorreu algo inesperado, tente novamente." << std::endl;
	}
}

void Trainer::SetY(double pos)
{
	int stat = WriteProcessMemory(Trainer::memory.hProc, (LPVOID)Trainer::TRAINER_Y, &pos, (DWORD)sizeof(pos), NULL);

	if (stat > 0){
		std::clog << "Sucesso ao escrever na memoria com valor: " << pos << std::endl;
	}
	else {
		std::cerr << "Ocorreu algo inesperado, tente novamente." << std::endl;
	}
}

void Trainer::SetZ(double pos)
{
	int stat = WriteProcessMemory(Trainer::memory.hProc, (LPVOID)Trainer::TRAINER_Z, &pos, (DWORD)sizeof(pos), NULL);

	if (stat > 0){
		std::clog << "Sucesso ao escrever na memoria com valor: " << pos << std::endl;
	}
	else {
		std::cerr << "Ocorreu algo inesperado, tente novamente." << std::endl;
	}
}

void Trainer::SetPos(double x,double y, double z)
{
	Trainer::SetX(x); Trainer::SetY(y); Trainer::SetZ(z);
}*/
<|endoftext|>


<commit_before>#include "../googletest/include/gtest/gtest.h"
#include "../include/easylogging++.h"
#include "../include/llg.hpp"
#include "../include/integrators.hpp"
#include "../include/io.hpp"
#include "../include/simulation.hpp"

INITIALIZE_EASYLOGGINGPP

TEST(llg, drift)
{
    double deriv[3];
    const double state[3] = {2, 3, 4};
    const double field[3] = {1, 2, 3};
    const double time=0, damping=3;
    llg::drift( deriv, state, time, damping, field );

    EXPECT_EQ( -34, deriv[0] );
    EXPECT_EQ(  -4, deriv[1] );
    EXPECT_EQ(  20, deriv[2] );
}

TEST(llg, diffusion)
{
    double deriv[3*3];
    const double state[3] = { 2, 3, 4 };
    const double time=0,  sr=2, alpha=3;
    llg::diffusion( deriv, state, time, sr, alpha );

    EXPECT_EQ( 150, deriv[0] );
    EXPECT_EQ( -28, deriv[1] );
    EXPECT_EQ ( -54, deriv[2] );
    EXPECT_EQ ( -44, deriv[3] );
    EXPECT_EQ ( 120, deriv[4] );
    EXPECT_EQ ( -68, deriv[5] );
    EXPECT_EQ ( -42, deriv[6] );
    EXPECT_EQ ( -76, deriv[7] );
    EXPECT_EQ ( 78, deriv[8] );
}

TEST(heun, 2d_wiener)
{
    double next_state[2];
    double drift_arr[2];
    double trial_drift_arr[2];
    double diffusion_matrix[4];
    double trial_diffusion_matrix[4];
    const double current_state[2] = { 0, 0 };
    const double wiener_steps[2] = { 0.1, 0.01 };

    const std::function<void(double*,const double*,const double)> drift =
        [](double *out, const double *in, const double t) { out[0]=0;out[1]=0; };
    const std::function<void(double*,const double*,const double)> diffusion =
        [](double *out, const double *in, const double t) { out[0]=1;out[1]=0;out[2]=0;out[3]=1; };

    const size_t n_dims=2, wiener_dims=2;
    const double t=0, step_size=1.44;

    integrator::heun(
        next_state, drift_arr, trial_drift_arr, diffusion_matrix, trial_diffusion_matrix,
        current_state, wiener_steps, drift, diffusion, n_dims, wiener_dims,
        t, step_size );

    EXPECT_FLOAT_EQ( 0.1, next_state[0] );
    EXPECT_FLOAT_EQ( 0.01, next_state[1] );
}

TEST(io, write_array)
{
    double arr[3] = {1, 2, 3}, arrback[3];
    int fail, nread;
    fail = io::write_array( "test.out", arr, 3 );
    ASSERT_EQ( 0, fail );

    // Read back the data
    FILE *in;
    in = fopen( "test.out", "rb" );
    nread = fread( arrback, sizeof(double), 3, in );
    fclose( in );

    ASSERT_EQ( 3, nread );
    ASSERT_FLOAT_EQ( 1, arrback[0] );
    ASSERT_FLOAT_EQ( 2, arrback[1] );
    ASSERT_FLOAT_EQ( 3, arrback[2] );

}

TEST( simulation, save_results )
{
    simulation::results res( 2 );

    res.magnetisation[0] = 2;
    res.magnetisation[1] = 3;
    res.field[0] = 4;
    res.field[1] = 5;
    res.time[0] = 6;
    res.time[1] = 7;

    simulation::save_results( "test.out", res );

    int nread;
    double arr[2];
    FILE *in;
    in=fopen( "test.out.mag", "rb" );
    nread = fread( arr, sizeof(double), 2, in );
    ASSERT_EQ( 2, nread );
    ASSERT_FLOAT_EQ( 2, arr[0] );
    ASSERT_FLOAT_EQ( 3, arr[1] );

    in=fopen( "test.out.field", "rb" );
    nread = fread( arr, sizeof(double), 2, in );
    ASSERT_EQ( 2, nread );
    ASSERT_FLOAT_EQ( 4, arr[0] );
    ASSERT_FLOAT_EQ( 5, arr[1] );

    in=fopen( "test.out.time", "rb" );
    nread = fread( arr, sizeof(double), 2, in );
    ASSERT_EQ( 2, nread );
    ASSERT_FLOAT_EQ( 6, arr[0] );
    ASSERT_FLOAT_EQ( 7, arr[1] );
}
<commit_msg>improve heun test and add driver test<commit_after>#include "../googletest/include/gtest/gtest.h"
#include "../include/easylogging++.h"
#include "../include/llg.hpp"
#include "../include/integrators.hpp"
#include "../include/io.hpp"
#include "../include/simulation.hpp"
#include <cmath>
#include <random>

INITIALIZE_EASYLOGGINGPP

TEST(llg, drift)
{
    double deriv[3];
    const double state[3] = {2, 3, 4};
    const double field[3] = {1, 2, 3};
    const double time=0, damping=3;
    llg::drift( deriv, state, time, damping, field );

    EXPECT_EQ( -34, deriv[0] );
    EXPECT_EQ(  -4, deriv[1] );
    EXPECT_EQ(  20, deriv[2] );
}

TEST(llg, diffusion)
{
    double deriv[3*3];
    const double state[3] = { 2, 3, 4 };
    const double time=0,  sr=2, alpha=3;
    llg::diffusion( deriv, state, time, sr, alpha );

    EXPECT_EQ( 150, deriv[0] );
    EXPECT_EQ( -28, deriv[1] );
    EXPECT_EQ ( -54, deriv[2] );
    EXPECT_EQ ( -44, deriv[3] );
    EXPECT_EQ ( 120, deriv[4] );
    EXPECT_EQ ( -68, deriv[5] );
    EXPECT_EQ ( -42, deriv[6] );
    EXPECT_EQ ( -76, deriv[7] );
    EXPECT_EQ ( 78, deriv[8] );
}

TEST(heun, multiplicative )
{
    double next_state[2];
    double drift_arr[2];
    double trial_drift_arr[2];
    double diffusion_matrix[6];
    double trial_diffusion_matrix[6];
    const double current_state[2] = { 1, 2 };
    const double wiener_steps[3] = { 0.1, 0.01, 0.001 };

    const std::function<void(double*,const double*,const double)> drift =
        [](double *out, const double *in, const double t) {
        out[0]=in[0]*in[1]*t; out[1]=3*in[0];
    };
    const std::function<void(double*,const double*,const double)> diffusion =
        [](double *out, const double *in, const double t) {
        out[0]=t; out[1]=in[0]; out[2]=in[1]; out[3]=in[1]; out[4]=4.0;
        out[5]=in[0]*in[1];
    };

    const size_t n_dims=2, wiener_dims=3;
    const double t=0, step_size=0.1;;

    integrator::heun(
        next_state, drift_arr, trial_drift_arr, diffusion_matrix, trial_diffusion_matrix,
        current_state, wiener_steps, drift, diffusion, n_dims, wiener_dims,
        t, step_size );

    EXPECT_FLOAT_EQ( 1.03019352, next_state[0] );
    EXPECT_FLOAT_EQ( 2.57118625, next_state[1] );
}

TEST(io, write_array)
{
    double arr[3] = {1, 2, 3}, arrback[3];
    int fail, nread;
    fail = io::write_array( "test.out", arr, 3 );
    ASSERT_EQ( 0, fail );

    // Read back the data
    FILE *in;
    in = fopen( "test.out", "rb" );
    nread = fread( arrback, sizeof(double), 3, in );
    fclose( in );

    ASSERT_EQ( 3, nread );
    ASSERT_DOUBLE_EQ( 1, arrback[0] );
    ASSERT_DOUBLE_EQ( 2, arrback[1] );
    ASSERT_DOUBLE_EQ( 3, arrback[2] );

}

TEST( simulation, save_results )
{
    simulation::results res( 2 );

    res.magnetisation[0] = 2;
    res.magnetisation[1] = 3;
    res.field[0] = 4;
    res.field[1] = 5;
    res.time[0] = 6;
    res.time[1] = 7;

    simulation::save_results( "test.out", res );

    int nread;
    double arr[2];
    FILE *in;
    in=fopen( "test.out.mag", "rb" );
    nread = fread( arr, sizeof(double), 2, in );
    ASSERT_EQ( 2, nread );
    ASSERT_DOUBLE_EQ( 2, arr[0] );
    ASSERT_DOUBLE_EQ( 3, arr[1] );

    in=fopen( "test.out.field", "rb" );
    nread = fread( arr, sizeof(double), 2, in );
    ASSERT_EQ( 2, nread );
    ASSERT_DOUBLE_EQ( 4, arr[0] );
    ASSERT_DOUBLE_EQ( 5, arr[1] );

    in=fopen( "test.out.time", "rb" );
    nread = fread( arr, sizeof(double), 2, in );
    ASSERT_EQ( 2, nread );
    ASSERT_DOUBLE_EQ( 6, arr[0] );
    ASSERT_DOUBLE_EQ( 7, arr[1] );
}

TEST( heun_driver, ou )
{
    const size_t n_steps = 5000;
    const size_t n_dims = 1;
    const size_t n_wiener = 1;
    const double step_size = 1e-5;
    const double initial_state[1]={-3};

    // define the Ornstein-Uhlenbeck process
    const double ou_theta = 10;
    const double ou_mu = -1;
    const double ou_sigma = 0.8;
    const std::function<void(double*,const double*,const double)> drift =
        [ou_theta,ou_mu](double *out, const double *in, const double t)
        { out[0]=ou_theta*(ou_mu - in[0]); };
    const std::function<void(double*,const double*,const double)> diffusion =
        [ou_sigma](double *out, const double *in, const double t) { out[0]=ou_sigma; };

    // Create a wiener path
    double wiener_process[n_steps];
    std::normal_distribution<double> dist( 0, std::sqrt( step_size ) );
    std::mt19937_64 rng;
    for( unsigned int i=0; i<n_steps; i++ )
        wiener_process[i] = dist( rng );

    // Generate the states
    double states[n_steps];
    driver::heun(
        states, initial_state, wiener_process, drift, diffusion,
        n_steps, n_dims, n_wiener, step_size );

    // Compute the analytic solution and compare pathwise similarity
    double truesol = initial_state[0];
    for( unsigned int i=1; i<n_steps; i++ )
    {
        truesol = truesol*std::exp( -ou_theta*step_size )
            + ou_mu*( 1-std::exp( -ou_theta*step_size ) )
            + ou_sigma*std::sqrt( ( 1- std::exp( -2*ou_theta*step_size ) )/( 2*ou_theta ) )
            * wiener_process[i-1]/std::sqrt( step_size );

        ASSERT_NEAR( truesol, states[i], 1e-8 );
    }
}
<|endoftext|>


<commit_before>// Copyright 2022 Michael Fisher <mfisher@lvtk.org>
// SPDX-License-Identifier: ISC

#include <algorithm>

#include "lvtk/ui/input.hpp"
#include "lvtk/ui/main.hpp"
#include "lvtk/ui/view.hpp"
#include "lvtk/ui/widget.hpp"

#define PUGL_DISABLE_DEPRECATED
#include <pugl/pugl.h>

// flip these for verbose logging
// #define VIEW_DBG(x) std::clog << x << std::endl;
#define VIEW_DBG(x)

namespace lvtk {
namespace detail {
template <typename Tp, class Ev>
static inline Point<Tp> point (const Ev& ev) {
    return {
        static_cast<Tp> (ev.x),
        static_cast<Tp> (ev.y)
    };
}

template <typename Tp, class Ev>
static inline Rectangle<Tp> rect (const Ev& ev) {
    return {
        static_cast<Tp> (ev.x),
        static_cast<Tp> (ev.y),
        static_cast<Tp> (ev.width),
        static_cast<Tp> (ev.height)
    };
}

template <typename Rect>
static inline PuglRect frame (const Rect& r) {
    return {
        static_cast<PuglCoord> (r.x),
        static_cast<PuglCoord> (r.y),
        static_cast<PuglSpan> (r.width),
        static_cast<PuglSpan> (r.height)
    };
}

inline static void erase (std::vector<View*>& views, View* view) {
    auto it = std::find (views.begin(), views.end(), view);
    if (it != views.end())
        views.erase (it);
}

} // namespace detail

struct View::EventHandler {
    static PuglStatus configure (View& view, const PuglConfigureEvent& ev) {
        if (ev.flags & PUGL_IS_HINT) {
            VIEW_DBG ("configure: hint");
            return PUGL_SUCCESS;
        }

        auto& w = view._widget;
        w.set_bounds (w.x(), w.y(), ev.width / view.scale_factor(), ev.height / view.scale_factor());
        VIEW_DBG ("pugl: configure: " << w.bounds().str());
        return PUGL_SUCCESS;
    }

    static PuglStatus expose (View& view, const PuglExposeEvent& ev) {
        if (ev.flags & PUGL_IS_HINT) {
            VIEW_DBG ("expose: hint");
            return PUGL_SUCCESS;
        }

        auto x = (float) ev.x / view.scale_factor();
        auto y = (float) ev.y / view.scale_factor();
        auto w = (float) ev.width / view.scale_factor();
        auto h = (float) ev.height / view.scale_factor();
        view.expose (Rectangle<float> { x, y, w, h }.as<int>());
        return PUGL_SUCCESS;
    }

    static PuglStatus create (View& view, const PuglCreateEvent& ev) {
        view.created();
        return PUGL_SUCCESS;
    }

    static PuglStatus destroy (View& view, const PuglDestroyEvent& ev) {
        view.destroyed();
        return PUGL_SUCCESS;
    }

    static PuglStatus map (View& view, const PuglMapEvent& ev) {
        return PUGL_SUCCESS;
    }

    static PuglStatus unmap (View& view, const PuglUnmapEvent& ev) {
        return PUGL_SUCCESS;
    }

    static PuglStatus update (View& view, const PuglUpdateEvent& ev) {
        return PUGL_SUCCESS;
    }

    static PuglStatus close (View& view, const PuglCloseEvent& ev) {
        // dirty setup so the demo can at least quit...
        if (view._main.mode() == Mode::PROGRAM)
            view._main.quit();
        return PUGL_SUCCESS;
    }

    static PuglStatus focus_in (View& view, const PuglFocusEvent& ev) { return PUGL_SUCCESS; }
    static PuglStatus focus_out (View& view, const PuglFocusEvent& ev) { return PUGL_SUCCESS; }
    static PuglStatus key_press (View& view, const PuglKeyEvent& ev) { return PUGL_SUCCESS; }
    static PuglStatus key_release (View& view, const PuglKeyEvent& ev) { return PUGL_SUCCESS; }
    static PuglStatus text (View& view, const PuglTextEvent& ev) { return PUGL_SUCCESS; }

    static PuglStatus pointer_in (View& view, const PuglCrossingEvent& ev) {
        VIEW_DBG ("pointer in")
        return PUGL_SUCCESS;
    }

    static PuglStatus pointer_out (View& view, const PuglCrossingEvent& ev) {
        VIEW_DBG ("pointer out")
        return PUGL_SUCCESS;
    }

    static PuglStatus motion (View& view, const PuglMotionEvent& ev) {
        auto pos      = detail::point<float> (ev) / view.scale_factor();
        WidgetRef ref = view._widget.widget_at (pos);

        InputEvent event;

        if (ref.valid()) {
            event.pos = ref->convert (&view._widget, pos);
            if (view._hovered != ref) {
                VIEW_DBG ("hovered changed: " << ref->__name);
                ref->pointer_in (event);
                view._hovered = ref;
            }

            ref->motion (event);
        } else if (view._hovered) {
            VIEW_DBG ("hovered cleared");

            if (auto h = view._hovered.lock()) {
                event.pos = h->convert (&view._widget, pos);
                h->pointer_out (event);
            }
            view._hovered = nullptr;
        }

        return PUGL_SUCCESS;
    }

    static PuglStatus button_press (View& view, const PuglButtonEvent& ev) {
        InputEvent event;
        event.pos = detail::point<float> (ev) / view.scale_factor();

        if (auto w = view._hovered.lock()) {
            event.pos = w->convert (&view._widget, event.pos);
            // VIEW_DBG("widget:" << w->__name << " bounds: " << w->bounds().str());
            // VIEW_DBG("ev pos: " << event.pos.str());
            if (w->contains (event.pos))
                w->pressed (event);
        }

        return PUGL_SUCCESS;
    }

    static PuglStatus button_release (View& view, const PuglButtonEvent& ev) {
        InputEvent event;
        event.pos    = detail::point<float> (ev) / view.scale_factor();
        auto hovered = view._hovered;

        if (auto w = hovered.lock()) {
            event.pos = hovered->convert (&view._widget, event.pos);
            if (w->contains (event.pos))
                w->released (event);
        }

        return PUGL_SUCCESS;
    }

    static PuglStatus scroll (View& view, const PuglScrollEvent& ev) { return PUGL_SUCCESS; }
    static PuglStatus client (View& view, const PuglClientEvent& ev) { return PUGL_SUCCESS; }
    static PuglStatus timer (View& view, const PuglTimerEvent& ev) { return PUGL_SUCCESS; }
    static PuglStatus loop_enter (View& view, const PuglLoopEnterEvent& ev) { return PUGL_SUCCESS; }
    static PuglStatus loop_leave (View& view, const PuglLoopLeaveEvent& ev) { return PUGL_SUCCESS; }
    static PuglStatus data_offer (View& view, const PuglDataOfferEvent& ev) { return PUGL_SUCCESS; }
    static PuglStatus data (View& view, const PuglDataEvent& ev) { return PUGL_SUCCESS; }
    static PuglStatus nothing (View&, const PuglAnyEvent&) { return PUGL_SUCCESS; }

    static inline PuglStatus dispatch (PuglView* v, const PuglEvent* ev) {
        auto view         = static_cast<View*> (puglGetHandle (v));
        PuglStatus status = PUGL_SUCCESS;

#define CASE3(t, fn, arg)         \
    case t:                       \
        status = fn (*view, arg); \
        break;
#define CASE2(t, fn) CASE3 (t, fn, ev->fn)
#define CASEA(t, fn) CASE3 (t, fn, ev->any)
        switch (ev->type) {
            CASE2 (PUGL_CONFIGURE, configure)                       //< View moved/resized, a #PuglConfigureEvent
            CASEA (PUGL_UPDATE, update)                             //< View ready to draw, a #PuglUpdateEvent
            CASE2 (PUGL_EXPOSE, expose)                             //< View must be drawn, a #PuglExposeEvent
            CASEA (PUGL_CREATE, create)                             //< View created, a #PuglCreateEvent
            CASEA (PUGL_DESTROY, destroy)                           ///< View destroyed, a #PuglDestroyEvent
            CASEA (PUGL_MAP, map)                                   ///< View made visible, a #PuglMapEvent
            CASEA (PUGL_UNMAP, unmap)                               ///< View made invisible, a #PuglUnmapEvent
            CASEA (PUGL_CLOSE, close)                               ///< View will be closed, a #PuglCloseEvent
            CASE3 (PUGL_FOCUS_IN, focus_in, ev->focus)              ///< Keyboard focus entered view, a #PuglFocusEvent
            CASE3 (PUGL_FOCUS_OUT, focus_out, ev->focus)            ///< Keyboard focus left view, a #PuglFocusEvent
            CASE3 (PUGL_KEY_PRESS, key_press, ev->key)              ///< Key pressed, a #PuglKeyEvent
            CASE3 (PUGL_KEY_RELEASE, key_release, ev->key)          ///< Key released, a #PuglKeyEvent
            CASE2 (PUGL_TEXT, text)                                 ///< Character entered, a #PuglTextEvent
            CASE3 (PUGL_POINTER_IN, pointer_in, ev->crossing)       ///< Pointer entered view, a #PuglCrossingEvent
            CASE3 (PUGL_POINTER_OUT, pointer_out, ev->crossing)     ///< Pointer left view, a #PuglCrossingEvent
            CASE3 (PUGL_BUTTON_PRESS, button_press, ev->button)     ///< Mouse button pressed, a #PuglButtonEvent
            CASE3 (PUGL_BUTTON_RELEASE, button_release, ev->button) ///< Mouse button released, a #PuglButtonEvent
            CASE2 (PUGL_MOTION, motion)                             ///< Pointer moved, a #PuglMotionEvent
            CASE2 (PUGL_SCROLL, scroll)                             ///< Scrolled, a #PuglScrollEvent
            CASE2 (PUGL_CLIENT, client)                             ///< Custom client message, a #PuglClientEvent
            CASE2 (PUGL_TIMER, timer)                               ///< Timer triggered, a #PuglTimerEvent
            CASEA (PUGL_LOOP_ENTER, loop_enter)                     ///< Recursive loop entered, a #PuglLoopEnterEvent
            CASEA (PUGL_LOOP_LEAVE, loop_leave)                     ///< Recursive loop left, a #PuglLoopLeaveEvent
            CASE3 (PUGL_DATA_OFFER, data_offer, ev->offer)          ///< Data offered from clipboard, a #PuglDataOfferEvent
            CASE2 (PUGL_DATA, data)                                 ///< Data available from clipboard, a #PuglDataEvent
            CASE3 (PUGL_NOTHING, nothing, ev->any)                  ///< No event
            default:
                break;
        }
#undef CASE2
#undef CASE3
#undef CASEA
        return status;
    }
};

View::View (Main& m, Widget& w)
    : _main (m),
      _widget (w) {
    _view  = (uintptr_t) puglNewView ((PuglWorld*) m.world());
    auto v = (PuglView*) _view;
    puglSetHandle (v, this);
    puglSetEventFunc (v, EventHandler::dispatch);
    _weak_status.reset (this);
    _main._views.push_back (this);
}

View::~View() {
    detail::erase (_main._views, this);
    _weak_status.reset();
    puglFreeView ((PuglView*) _view);
    _view = (uintptr_t) nullptr;
}

void View::set_backend (uintptr_t b) {
    puglSetBackend ((PuglView*) _view, (PuglBackend*) b);
}

void View::set_view_hint (int hint, int value) {
    puglSetViewHint ((PuglView*) _view, static_cast<PuglViewHint> (hint), value);
}

uintptr_t View::handle() { return puglGetNativeView ((PuglView*) _view); }
float View::scale_factor() const noexcept { return static_cast<float> (puglGetScaleFactor ((PuglView*) _view)); }

void View::set_visible (bool visible) {
    if (visible)
        puglShow ((PuglView*) _view);
    else
        puglHide ((PuglView*) _view);
}

bool View::visible() const { return puglGetVisible ((PuglView*) _view); }

void View::set_size (int width, int height) {
    puglSetSize ((PuglView*) _view, width * scale_factor(), height * scale_factor());
}

Rectangle<int> View::bounds() const {
    auto f = puglGetFrame ((PuglView*) _view);
    return {
        static_cast<int> ((float) f.x / scale_factor()),
        static_cast<int> ((float) f.y / scale_factor()),
        static_cast<int> ((float) f.width / scale_factor()),
        static_cast<int> ((float) f.height / scale_factor())
    };
}

void View::set_bounds (Bounds b) {
    b *= scale_factor();
    puglSetFrame ((PuglView*) _view, detail::frame (b));
}

void View::realize() {
    puglRealize ((PuglView*) _view);
}

Style& View::style() noexcept { return _main.style(); }
const Style& View::style() const noexcept { return _main.style(); }

void View::elevate (Widget& widget, ViewFlags flags) {
    _main.elevate (widget, flags, *this);
}

//==
void View::render (Surface& ctx) {
    Graphics g (ctx);
    _widget.render (g);
}

void View::set_parent (uintptr_t parent, bool transient) {
    if (! parent)
        return;
    if (transient)
        puglSetTransientParent ((PuglView*) _view, parent);
    else
        puglSetParentWindow ((PuglView*) _view, parent);
}

void View::__pugl_post_redisplay() {
    puglPostRedisplay ((PuglView*) _view);
}

} // namespace lvtk
<commit_msg>limit pointer_out coords to widget local bounds<commit_after>// Copyright 2022 Michael Fisher <mfisher@lvtk.org>
// SPDX-License-Identifier: ISC

#include <algorithm>

#include "lvtk/ui/input.hpp"
#include "lvtk/ui/main.hpp"
#include "lvtk/ui/view.hpp"
#include "lvtk/ui/widget.hpp"

#define PUGL_DISABLE_DEPRECATED
#include <pugl/pugl.h>

// flip these for verbose logging
// #define VIEW_DBG(x) std::clog << x << std::endl;
#define VIEW_DBG(x)

namespace lvtk {
namespace detail {
template <typename Tp, class Ev>
static inline Point<Tp> point (const Ev& ev) {
    return {
        static_cast<Tp> (ev.x),
        static_cast<Tp> (ev.y)
    };
}

template <typename Tp, class Ev>
static inline Rectangle<Tp> rect (const Ev& ev) {
    return {
        static_cast<Tp> (ev.x),
        static_cast<Tp> (ev.y),
        static_cast<Tp> (ev.width),
        static_cast<Tp> (ev.height)
    };
}

template <typename Rect>
static inline PuglRect frame (const Rect& r) {
    return {
        static_cast<PuglCoord> (r.x),
        static_cast<PuglCoord> (r.y),
        static_cast<PuglSpan> (r.width),
        static_cast<PuglSpan> (r.height)
    };
}

inline static void erase (std::vector<View*>& views, View* view) {
    auto it = std::find (views.begin(), views.end(), view);
    if (it != views.end())
        views.erase (it);
}

} // namespace detail

struct View::EventHandler {
    static PuglStatus configure (View& view, const PuglConfigureEvent& ev) {
        if (ev.flags & PUGL_IS_HINT) {
            VIEW_DBG ("configure: hint");
            return PUGL_SUCCESS;
        }

        auto& w = view._widget;
        w.set_bounds (w.x(), w.y(), ev.width / view.scale_factor(), ev.height / view.scale_factor());
        VIEW_DBG ("pugl: configure: " << w.bounds().str());
        return PUGL_SUCCESS;
    }

    static PuglStatus expose (View& view, const PuglExposeEvent& ev) {
        if (ev.flags & PUGL_IS_HINT) {
            VIEW_DBG ("expose: hint");
            return PUGL_SUCCESS;
        }

        auto x = (float) ev.x / view.scale_factor();
        auto y = (float) ev.y / view.scale_factor();
        auto w = (float) ev.width / view.scale_factor();
        auto h = (float) ev.height / view.scale_factor();
        view.expose (Rectangle<float> { x, y, w, h }.as<int>());
        return PUGL_SUCCESS;
    }

    static PuglStatus create (View& view, const PuglCreateEvent& ev) {
        view.created();
        return PUGL_SUCCESS;
    }

    static PuglStatus destroy (View& view, const PuglDestroyEvent& ev) {
        view.destroyed();
        return PUGL_SUCCESS;
    }

    static PuglStatus map (View& view, const PuglMapEvent& ev) {
        return PUGL_SUCCESS;
    }

    static PuglStatus unmap (View& view, const PuglUnmapEvent& ev) {
        return PUGL_SUCCESS;
    }

    static PuglStatus update (View& view, const PuglUpdateEvent& ev) {
        return PUGL_SUCCESS;
    }

    static PuglStatus close (View& view, const PuglCloseEvent& ev) {
        // dirty setup so the demo can at least quit...
        if (view._main.mode() == Mode::PROGRAM)
            view._main.quit();
        return PUGL_SUCCESS;
    }

    static PuglStatus focus_in (View& view, const PuglFocusEvent& ev) { return PUGL_SUCCESS; }
    static PuglStatus focus_out (View& view, const PuglFocusEvent& ev) { return PUGL_SUCCESS; }
    static PuglStatus key_press (View& view, const PuglKeyEvent& ev) { return PUGL_SUCCESS; }
    static PuglStatus key_release (View& view, const PuglKeyEvent& ev) { return PUGL_SUCCESS; }
    static PuglStatus text (View& view, const PuglTextEvent& ev) { return PUGL_SUCCESS; }

    static PuglStatus pointer_in (View& view, const PuglCrossingEvent& ev) {
        VIEW_DBG ("pointer in")
        return PUGL_SUCCESS;
    }

    static PuglStatus pointer_out (View& view, const PuglCrossingEvent& ev) {
        VIEW_DBG ("pointer out")
        return PUGL_SUCCESS;
    }

    static PuglStatus motion (View& view, const PuglMotionEvent& ev) {
        auto pos      = detail::point<float> (ev) / view.scale_factor();
        WidgetRef ref = view._widget.widget_at (pos);

        InputEvent event;

        if (ref.valid()) {
            event.pos = ref->convert (&view._widget, pos);
            if (view._hovered != ref) {
                VIEW_DBG ("hovered changed: " << ref->__name);
                ref->pointer_in (event);
                view._hovered = ref;
            }

            ref->motion (event);
        } else if (view._hovered) {
            VIEW_DBG ("hovered cleared");

            if (auto h = view._hovered.lock()) {
                event.pos = h->convert (&view._widget, pos);
                event.pos.x = std::min (std::max (0.f, event.pos.x), (float)h->width());
                event.pos.y = std::min (std::max (0.f, event.pos.y), (float)h->height());
                h->pointer_out (event);
            }
            view._hovered = nullptr;
        }

        return PUGL_SUCCESS;
    }

    static PuglStatus button_press (View& view, const PuglButtonEvent& ev) {
        InputEvent event;
        event.pos = detail::point<float> (ev) / view.scale_factor();

        if (auto w = view._hovered.lock()) {
            event.pos = w->convert (&view._widget, event.pos);
            // VIEW_DBG("widget:" << w->__name << " bounds: " << w->bounds().str());
            // VIEW_DBG("ev pos: " << event.pos.str());
            if (w->contains (event.pos))
                w->pressed (event);
        }

        return PUGL_SUCCESS;
    }

    static PuglStatus button_release (View& view, const PuglButtonEvent& ev) {
        InputEvent event;
        event.pos    = detail::point<float> (ev) / view.scale_factor();
        auto hovered = view._hovered;

        if (auto w = hovered.lock()) {
            event.pos = hovered->convert (&view._widget, event.pos);
            if (w->contains (event.pos))
                w->released (event);
        }

        return PUGL_SUCCESS;
    }

    static PuglStatus scroll (View& view, const PuglScrollEvent& ev) { return PUGL_SUCCESS; }
    static PuglStatus client (View& view, const PuglClientEvent& ev) { return PUGL_SUCCESS; }
    static PuglStatus timer (View& view, const PuglTimerEvent& ev) { return PUGL_SUCCESS; }
    static PuglStatus loop_enter (View& view, const PuglLoopEnterEvent& ev) { return PUGL_SUCCESS; }
    static PuglStatus loop_leave (View& view, const PuglLoopLeaveEvent& ev) { return PUGL_SUCCESS; }
    static PuglStatus data_offer (View& view, const PuglDataOfferEvent& ev) { return PUGL_SUCCESS; }
    static PuglStatus data (View& view, const PuglDataEvent& ev) { return PUGL_SUCCESS; }
    static PuglStatus nothing (View&, const PuglAnyEvent&) { return PUGL_SUCCESS; }

    static inline PuglStatus dispatch (PuglView* v, const PuglEvent* ev) {
        auto view         = static_cast<View*> (puglGetHandle (v));
        PuglStatus status = PUGL_SUCCESS;

#define CASE3(t, fn, arg)         \
    case t:                       \
        status = fn (*view, arg); \
        break;
#define CASE2(t, fn) CASE3 (t, fn, ev->fn)
#define CASEA(t, fn) CASE3 (t, fn, ev->any)
        switch (ev->type) {
            CASE2 (PUGL_CONFIGURE, configure)                       //< View moved/resized, a #PuglConfigureEvent
            CASEA (PUGL_UPDATE, update)                             //< View ready to draw, a #PuglUpdateEvent
            CASE2 (PUGL_EXPOSE, expose)                             //< View must be drawn, a #PuglExposeEvent
            CASEA (PUGL_CREATE, create)                             //< View created, a #PuglCreateEvent
            CASEA (PUGL_DESTROY, destroy)                           ///< View destroyed, a #PuglDestroyEvent
            CASEA (PUGL_MAP, map)                                   ///< View made visible, a #PuglMapEvent
            CASEA (PUGL_UNMAP, unmap)                               ///< View made invisible, a #PuglUnmapEvent
            CASEA (PUGL_CLOSE, close)                               ///< View will be closed, a #PuglCloseEvent
            CASE3 (PUGL_FOCUS_IN, focus_in, ev->focus)              ///< Keyboard focus entered view, a #PuglFocusEvent
            CASE3 (PUGL_FOCUS_OUT, focus_out, ev->focus)            ///< Keyboard focus left view, a #PuglFocusEvent
            CASE3 (PUGL_KEY_PRESS, key_press, ev->key)              ///< Key pressed, a #PuglKeyEvent
            CASE3 (PUGL_KEY_RELEASE, key_release, ev->key)          ///< Key released, a #PuglKeyEvent
            CASE2 (PUGL_TEXT, text)                                 ///< Character entered, a #PuglTextEvent
            CASE3 (PUGL_POINTER_IN, pointer_in, ev->crossing)       ///< Pointer entered view, a #PuglCrossingEvent
            CASE3 (PUGL_POINTER_OUT, pointer_out, ev->crossing)     ///< Pointer left view, a #PuglCrossingEvent
            CASE3 (PUGL_BUTTON_PRESS, button_press, ev->button)     ///< Mouse button pressed, a #PuglButtonEvent
            CASE3 (PUGL_BUTTON_RELEASE, button_release, ev->button) ///< Mouse button released, a #PuglButtonEvent
            CASE2 (PUGL_MOTION, motion)                             ///< Pointer moved, a #PuglMotionEvent
            CASE2 (PUGL_SCROLL, scroll)                             ///< Scrolled, a #PuglScrollEvent
            CASE2 (PUGL_CLIENT, client)                             ///< Custom client message, a #PuglClientEvent
            CASE2 (PUGL_TIMER, timer)                               ///< Timer triggered, a #PuglTimerEvent
            CASEA (PUGL_LOOP_ENTER, loop_enter)                     ///< Recursive loop entered, a #PuglLoopEnterEvent
            CASEA (PUGL_LOOP_LEAVE, loop_leave)                     ///< Recursive loop left, a #PuglLoopLeaveEvent
            CASE3 (PUGL_DATA_OFFER, data_offer, ev->offer)          ///< Data offered from clipboard, a #PuglDataOfferEvent
            CASE2 (PUGL_DATA, data)                                 ///< Data available from clipboard, a #PuglDataEvent
            CASE3 (PUGL_NOTHING, nothing, ev->any)                  ///< No event
            default:
                break;
        }
#undef CASE2
#undef CASE3
#undef CASEA
        return status;
    }
};

View::View (Main& m, Widget& w)
    : _main (m),
      _widget (w) {
    _view  = (uintptr_t) puglNewView ((PuglWorld*) m.world());
    auto v = (PuglView*) _view;
    puglSetHandle (v, this);
    puglSetEventFunc (v, EventHandler::dispatch);
    _weak_status.reset (this);
    _main._views.push_back (this);
}

View::~View() {
    detail::erase (_main._views, this);
    _weak_status.reset();
    puglFreeView ((PuglView*) _view);
    _view = (uintptr_t) nullptr;
}

void View::set_backend (uintptr_t b) {
    puglSetBackend ((PuglView*) _view, (PuglBackend*) b);
}

void View::set_view_hint (int hint, int value) {
    puglSetViewHint ((PuglView*) _view, static_cast<PuglViewHint> (hint), value);
}

uintptr_t View::handle() { return puglGetNativeView ((PuglView*) _view); }
float View::scale_factor() const noexcept { return static_cast<float> (puglGetScaleFactor ((PuglView*) _view)); }

void View::set_visible (bool visible) {
    if (visible)
        puglShow ((PuglView*) _view);
    else
        puglHide ((PuglView*) _view);
}

bool View::visible() const { return puglGetVisible ((PuglView*) _view); }

void View::set_size (int width, int height) {
    puglSetSize ((PuglView*) _view, width * scale_factor(), height * scale_factor());
}

Rectangle<int> View::bounds() const {
    auto f = puglGetFrame ((PuglView*) _view);
    return {
        static_cast<int> ((float) f.x / scale_factor()),
        static_cast<int> ((float) f.y / scale_factor()),
        static_cast<int> ((float) f.width / scale_factor()),
        static_cast<int> ((float) f.height / scale_factor())
    };
}

void View::set_bounds (Bounds b) {
    b *= scale_factor();
    puglSetFrame ((PuglView*) _view, detail::frame (b));
}

void View::realize() {
    puglRealize ((PuglView*) _view);
}

Style& View::style() noexcept { return _main.style(); }
const Style& View::style() const noexcept { return _main.style(); }

void View::elevate (Widget& widget, ViewFlags flags) {
    _main.elevate (widget, flags, *this);
}

//==
void View::render (Surface& ctx) {
    Graphics g (ctx);
    _widget.render (g);
}

void View::set_parent (uintptr_t parent, bool transient) {
    if (! parent)
        return;
    if (transient)
        puglSetTransientParent ((PuglView*) _view, parent);
    else
        puglSetParentWindow ((PuglView*) _view, parent);
}

void View::__pugl_post_redisplay() {
    puglPostRedisplay ((PuglView*) _view);
}

} // namespace lvtk
<|endoftext|>


<commit_before>#include "../mtl.hpp"
#include "../src/debug.hpp"
#include <iostream>

using A = std::tuple<int, int>;
using B = std::tuple<long, char>;

// Has type
// ================================================================================
static_assert(mtl::has_type<char, B>::value, "");
static_assert(mtl::has_type<long, B>::value, "");
static_assert(!mtl::has_type<int, B>::value, "");

// Concat
// ================================================================================
using C = mtl::concat<A, B>;
using D = mtl::concat<A>;
using E = mtl::concat<A, B, C, D>;
static_assert(std::tuple_size<C>::value == 4, "C should be size of 4");
static_assert(std::tuple_size<D>::value == 2, "D should be size of 2");
static_assert(std::tuple_size<E>::value == 10, "E should be size of 10");

// Head
// ================================================================================
static_assert(std::is_same<long,
                           mtl::head<B>>::value, "");

// Index of type

// Select
// ================================================================================
static_assert(std::is_same<std::tuple<char, int>,
                           mtl::select<C, 3, 1>>::value, "");

// Tail
// ================================================================================
static_assert(std::is_same<std::tuple<int, long, char>,
                           mtl::tail<C>>::value, "");

// Transform
// ================================================================================
static_assert(std::is_same<std::tuple<int, int>,
                           mtl::transform<B, mtl::transform_to<int>::value>>::value, "");
static_assert(std::is_same<std::tuple<long, char>,
                           mtl::transform<B, mtl::identity>>::value, "");

// Filter
// ================================================================================
template<typename T>
    struct no_ints {
        static constexpr auto value = !std::is_same<T, int>::value;
    };

static_assert(std::is_same<std::tuple<char, float>,
                           mtl::filter<no_ints, std::tuple<int, char, int, float>>>::value, "");

// Unique
// ================================================================================
static_assert(std::is_same<std::tuple<int, char, float, long>,
                           mtl::unique<std::tuple<int, char, int, float, char, long>>>::value, "");

// Without
// ================================================================================
static_assert(std::is_same<std::tuple<char, float, char, long>,
                           mtl::without<int, std::tuple<int, char, int, float, char, long>>>::value, "");

// Interleave
// ================================================================================
static_assert(std::is_same<std::tuple<int, long, char, long, int, long>,
                           mtl::interleave<std::tuple<int, char, int>, std::tuple<long, long, long>>>::value, "");
static_assert(std::is_same<std::tuple<int, char, char>,
                           mtl::interleave<std::tuple<int>, std::tuple<char, char>>>::value, "");

// Merge
// ================================================================================
using MA = std::tuple<float, int, float>;
using MB = std::tuple<int, char, char>;
using MVec = std::tuple<float, int, char>;

using MC = mtl::merge<MA, MB, MVec>;
static_assert(std::tuple_size<MC>::value == 6, "");
static_assert(std::is_same<std::tuple<float, int, float, int, char, char>, MC>::value, "");

// Sort
// ================================================================================
using ST = std::tuple<int, char, int, int, float, char, float, int>;
using SV = std::tuple<char, int, float>;
using SC = mtl::sort<ST, SV>;
static_assert(std::is_same<std::tuple<char, char, int, int, int, int, float, float>, SC>::value, "");

int main() { return 0; }
<commit_msg>Cleanup<commit_after>#include "../mtl.hpp"
#include "../src/debug.hpp"
#include <iostream>

using A = std::tuple<int, int>;
using B = std::tuple<long, char>;

// Has type
// ================================================================================
static_assert(mtl::has_type<char, B>::value, "");
static_assert(mtl::has_type<long, B>::value, "");
static_assert(!mtl::has_type<int, B>::value, "");

// Concat
// ================================================================================
using C = mtl::concat<A, B>;
using D = mtl::concat<A>;
using E = mtl::concat<A, B, C, D>;
static_assert(std::tuple_size<C>::value == 4, "C should be size of 4");
static_assert(std::tuple_size<D>::value == 2, "D should be size of 2");
static_assert(std::tuple_size<E>::value == 10, "E should be size of 10");

// Head
// ================================================================================
static_assert(std::is_same<long,
                           mtl::head<B>>::value, "");

// Index of type

// Select
// ================================================================================
static_assert(std::is_same<std::tuple<char, int>,
                           mtl::select<C, 3, 1>>::value, "");

// Tail
// ================================================================================
static_assert(std::is_same<std::tuple<int, long, char>,
                           mtl::tail<C>>::value, "");

// Transform
// ================================================================================
static_assert(std::is_same<std::tuple<int, int>,
                           mtl::transform<B, mtl::transform_to<int>::value>>::value, "");
static_assert(std::is_same<std::tuple<long, char>,
                           mtl::transform<B, mtl::identity>>::value, "");

// Filter
// ================================================================================
template<typename T>
    struct no_ints {
        static constexpr auto value = !std::is_same<T, int>::value;
    };

static_assert(std::is_same<std::tuple<char, float>,
                           mtl::filter<no_ints, std::tuple<int, char, int, float>>>::value, "");

// Unique
// ================================================================================
static_assert(std::is_same<std::tuple<int, char, float, long>,
                           mtl::unique<std::tuple<int, char, int, float, char, long>>>::value, "");

// Without
// ================================================================================
static_assert(std::is_same<std::tuple<char, float, char, long>,
                           mtl::without<int, std::tuple<int, char, int, float, char, long>>>::value, "");

// Interleave
// ================================================================================
static_assert(std::is_same<std::tuple<int, long, char, long, int, long>,
                           mtl::interleave<std::tuple<int, char, int>, std::tuple<long, long, long>>>::value, "");
static_assert(std::is_same<std::tuple<int, char, char>,
                           mtl::interleave<std::tuple<int>, std::tuple<char, char>>>::value, "");

// Merge
// ================================================================================
using MA = std::tuple<float, int, float>;
using MB = std::tuple<int, char, char>;
using MC = mtl::merge<MA, MB, std::tuple<float, int, char>>;
static_assert(std::is_same<std::tuple<float, int, float, int, char, char>, MC>::value, "");

// Sort
// ================================================================================
using ST = std::tuple<int, char, int, int, float, char, float, int>;
using SC = mtl::sort<ST, std::tuple<char, int, float>>;
static_assert(std::is_same<std::tuple<char, char, int, int, int, int, float, float>, SC>::value, "");

int main() { return 0; }
<|endoftext|>