<commit_before>/* Copyright (C) 2010 The Trustees of Indiana University.                  */
/*                                                                         */
/* Use, modification and distribution is subject to the Boost Software     */
/* License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at */
/* http://www.boost.org/LICENSE_1_0.txt)                                   */
/*                                                                         */
/*  Authors: Jeremiah Willcock                                             */
/*           Andrew Lumsdaine                                              */

/* These need to be before any possible inclusions of stdint.h or inttypes.h.
 * */
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS
#endif
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif

#include "../generator/make_graph.h"
#include "../generator/utils.h"
#include "common.h"
#include <math.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <limits.h>
#include <stdint.h>
#include <inttypes.h>

#include "SoftXMT.hpp"
#include "GlobalAllocator.hpp"
#include "ForkJoin.hpp"
#include "Cache.hpp"
#include "timer.h"

static int compare_doubles(const void* a, const void* b) {
  double aa = *(const double*)a;
  double bb = *(const double*)b;
  return (aa < bb) ? -1 : (aa == bb) ? 0 : 1;
}
enum {s_minimum, s_firstquartile, s_median, s_thirdquartile, s_maximum, s_mean, s_std, s_LAST};
static void get_statistics(const double x[], int n, double r[s_LAST]);

//### Globals ###
#define MAX_SCALE 20

int lgsize;
double A = 0.57;
double B = 0.19;
double C = 0.19;
double D = 1.0-(A+B+C);

static mrg_state prng_state_store;

#define NRAND(ne) (5 * SCALE * (ne))

struct func_initialize : public ForkJoinIteration {
  GlobalAddress<int64_t> base_addr;
  int64_t value;
  void operator()(thread * me, int64_t index) {
    SLOG(2) << "called func_initialize with index = " << index;
    Incoherent<int64_t>::RW c(base_addr+index, 1);
    c[0] = value+index;
  }
};

struct randpermute_func : public ForkJoinIteration {
  GlobalAddress<int64_t> array;
  int64_t nelem;
  mrg_state st;
  void operator()(thread * me, int64_t index) {
    int64_t k = index;
    int64_t place;
//    elt_type Ak, Aplace;
//    Ak = take (&array[k]);
    Incoherent<int64_t>::RW Ak(array+k, 1);

    mrg_skip(&st, 1, k, 0);

    place = k + (int64_t)floor( mrg_get_double_orig(&st) * (nelem - k) );
    if (k != place) {
      assert (place > k);
      assert (place < nelem);
//      Aplace = take (&array[place]);
      Incoherent<int64_t>::RW Aplace(array+place, 1);
      {
        int64_t t;
        t = array[place];
        array[place] = array[k];
        array[k] = t;
      }
      {
        elt_type t;
        t = Aplace;
        Aplace = Ak;
        Ak = t;
      }
//      release (&array[place], Aplace);
    }
    release (&array[k], Ak);
  }
};

static void permute_vertex_labels (packed_edge * restrict IJ, int64_t nedge, int64_t max_nvtx, mrg_state * restrict st, GlobalAddress<int64_t> newlabel) {
	int64_t k;

//  OMP("omp for")
//	for (k = 0; k < max_nvtx; ++k)
//		newlabel[k] = k;
  {
    func_initialize f;
      f.base_addr = newlabel;
      f.value = 0.0;
    fork_join(current_thread, &f, 0, max_nvtx);
  }

  //	randpermute(newlabel, max_nvtx, st);
	{
    randpermute_func f;
      f.array = newlabel;
      f.nelem = max_nvtx;
      f.st = *st;
    fork_join(current_thread, &f, 0, max_nvtx);
  }

	OMP("omp for")
	for (k = 0; k < nedge; ++k)
		write_edge(&IJ[k],
               newlabel[get_v0_from_edge(&IJ[k])],
               newlabel[get_v1_from_edge(&IJ[k])]);
}

static void permute_edgelist(packed_edge * restrict IJ, int64_t nedge, mrg_state *st) {
	randpermute(IJ, nedge, st);
}

static void rmat_edge(packed_edge *out, int SCALE, double A, double B, double C, double D, const double *rn) {
	size_t rni = 0;
	int64_t i = 0, j = 0;
	int64_t bit = ((int64_t)1) << (SCALE-1);

	while (1) {
		const double r = rn[rni++];
		if (r > A) { /* outside quadrant 1 */
			if (r <= A + B) /* in quadrant 2 */
				j |= bit;
			else if (r <= A + B + C) /* in quadrant 3 */
				i |= bit;
			else { /* in quadrant 4 */
				j |= bit;
				i |= bit;
			}
		}
		if (1 == bit) break;

		/*
		 Assuming R is in (0, 1), 0.95 + 0.1 * R is in (0.95, 1.05).
		 So the new probabilities are *not* the old +/- 10% but
		 instead the old +/- 5%.
		 */
		A *= 0.95 + rn[rni++]/10;
		B *= 0.95 + rn[rni++]/10;
		C *= 0.95 + rn[rni++]/10;
		D *= 0.95 + rn[rni++]/10;
		/* Used 5 random numbers. */

		{
			const double norm = 1.0 / (A + B + C + D);
			A *= norm; B *= norm; C *= norm;
		}
		/* So long as +/- are monotonic, ensure a+b+c+d <= 1.0 */
		D = 1.0 - (A + B + C);

		bit >>= 1;
	}
	/* Iterates SCALE times. */
	write_edge(out, i, j);
}

struct random_edges_functor : public ForkJoinIteration {
  GlobalAddress<packed_edge> ij;
  GlobalAddress<int64_t> iwork;
  int64_t nedge;
  mrg_state prng_state;
  int SCALE;
  void operator()(thread * me, int64_t index) {
    double * restrict Rlocal = (double*)alloca(NRAND(1) * sizeof(double));
    mrg_state new_st = prng_state;
    mrg_skip(&new_st, 1, NRAND(1), 0);
    for (int64_t i; i < NRAND(1); i++) {
      Rlocal[i] = mrg_get_double_orig(&new_st);
    }
    packed_edge new_edge;
    rmat_edge(&new_edge, SCALE, A, B, C, D, Rlocal);

    Incoherent<packed_edge>::RW cedge(ij+index, 1);
    *cedge = new_edge;
  }
};

static void rmat_edgelist(tuple_graph* grin, int SCALE) {
  GlobalAddress<int64_t> iwork = SoftXMT_typed_malloc<int64_t>(1L<<SCALE);

  random_edges_functor f;
  f.iwork = iwork;
  f.nedge = grin->nedge;
  f.prng_state = prng_state_store;
  f.SCALE = SCALE;
  fork_join(current_thread, &f, 0, grin->nedge);

  mrg_skip(&prng_state_store, 1, NRAND(1), 0);

}

int main(int argc, char** argv) {
  SoftXMT_init(&argc, &argv, 1<<(MAX_SCALE+2));
  SoftXMT_activate();

  Node rank = SoftXMT_mynode();

  /* Parse arguments. */
  int SCALE = 16;
  int edgefactor = 16; /* nedges / nvertices, i.e., 2*avg. degree */
  if (argc >= 2) SCALE = atoi(argv[1]);
  if (argc >= 3) edgefactor = atoi(argv[2]);
  if (argc <= 1 || argc >= 4 || SCALE == 0 || edgefactor == 0) {
    if (rank == 0) {
      fprintf(stderr, "Usage: %s SCALE edgefactor\n  SCALE = log_2(# vertices) [integer, required]\n  edgefactor = (# edges) / (# vertices) = .5 * (average vertex degree) [integer, defaults to 16]\n(Random number seed and Kronecker initiator are in main.c)\n", argv[0]);
    }
  }
  assert(SCALE <= MAX_SCALE);
  uint64_t seed1 = 2, seed2 = 3;

  tuple_graph tg;
  tg.nedge = (int64_t)(edgefactor) << SCALE;
  int64_t nglobalverts = (int64_t)(1) << SCALE;

  /* Make the raw graph edges. */
  /* Get roots for BFS runs, plus maximum vertex with non-zero degree (used by
   * validator). */
  int num_bfs_roots = 64;
//  int64_t* bfs_roots = (int64_t*)xmalloc(num_bfs_roots * sizeof(int64_t));
  GlobalAddress<int64_t> bfs_roots = SoftXMT_typed_malloc<int64_t>(num_bfs_roots);
  int64_t max_used_vertex = 0;

  double start, stop;
  start = timer();
  {
    /* Spread the two 64-bit numbers into five nonzero values in the correct
     * range. */
    uint_fast32_t seed[5];
    make_mrg_seed(seed1, seed2, seed);
    mrg_seed(&prng_state_store, seed);

    /* As the graph is being generated, also keep a bitmap of vertices with
     * incident edges.  We keep a grid of processes, each row of which has a
     * separate copy of the bitmap (distributed among the processes in the
     * row), and then do an allreduce at the end.  This scheme is used to avoid
     * non-local communication and reading the file separately just to find BFS
     * roots. */
    tg.edges = SoftXMT_typed_malloc<packed_edge>(tg.nedge);

    rmat_edgelist(&tg, SCALE);

    //TODO
  }
  stop = timer();
  double make_graph_time = stop - start;
  if (rank == 0) { /* Not an official part of the results */
    fprintf(stderr, "graph_generation:               %f s\n", make_graph_time);
  }

  SoftXMT_free(bfs_roots);
  free_graph_data_structure();

  SoftXMT_free(tg.edges);

  /* Print results. */

  SoftXMT_finish(0);
  return 0;
}

static void get_statistics(const double x[], int n, double r[s_LAST]) {
  double temp;
  int i;
  /* Compute mean. */
  temp = 0;
  for (i = 0; i < n; ++i) temp += x[i];
  temp /= n;
  r[s_mean] = temp;
  /* Compute std. dev. */
  temp = 0;
  for (i = 0; i < n; ++i) temp += (x[i] - r[s_mean]) * (x[i] - r[s_mean]);
  temp /= n - 1;
  r[s_std] = sqrt(temp);
  /* Sort x. */
  double* xx = (double*)xmalloc(n * sizeof(double));
  memcpy(xx, x, n * sizeof(double));
  qsort(xx, n, sizeof(double), compare_doubles);
  /* Get order statistics. */
  r[s_minimum] = xx[0];
  r[s_firstquartile] = (xx[(n - 1) / 4] + xx[n / 4]) * .5;
  r[s_median] = (xx[(n - 1) / 2] + xx[n / 2]) * .5;
  r[s_thirdquartile] = (xx[n - 1 - (n - 1) / 4] + xx[n - 1 - n / 4]) * .5;
  r[s_maximum] = xx[n - 1];
  /* Clean up. */
  free(xx);
}

<commit_msg>Now correctly (I think) doing rmat generation.<commit_after>/* Copyright (C) 2010 The Trustees of Indiana University.                  */
/*                                                                         */
/* Use, modification and distribution is subject to the Boost Software     */
/* License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at */
/* http://www.boost.org/LICENSE_1_0.txt)                                   */
/*                                                                         */
/*  Authors: Jeremiah Willcock                                             */
/*           Andrew Lumsdaine                                              */

/* These need to be before any possible inclusions of stdint.h or inttypes.h.
 * */
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS
#endif
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif

#include "../generator/make_graph.h"
#include "../generator/utils.h"
#include "common.h"
#include <math.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <limits.h>
#include <stdint.h>
#include <inttypes.h>

#include "SoftXMT.hpp"
#include "GlobalAllocator.hpp"
#include "ForkJoin.hpp"
#include "Cache.hpp"
#include "Delegate.hpp"
#include "timer.h"

static int compare_doubles(const void* a, const void* b) {
  double aa = *(const double*)a;
  double bb = *(const double*)b;
  return (aa < bb) ? -1 : (aa == bb) ? 0 : 1;
}
enum {s_minimum, s_firstquartile, s_median, s_thirdquartile, s_maximum, s_mean, s_std, s_LAST};
static void get_statistics(const double x[], int n, double r[s_LAST]);

//### Globals ###
int SCALE;
int edgefactor;

#define MAX_SCALE 20

int lgsize;
double A = 0.57;
double B = 0.19;
double C = 0.19;
double D = 1.0-(A+B+C);

static mrg_state prng_state_store;

#define NRAND(ne) (5 * SCALE * (ne))

struct func_initialize : public ForkJoinIteration {
  GlobalAddress<int64_t> base_addr;
  int64_t value;
  void operator()(thread * me, int64_t index) {
    DVLOG(1) << "called func_initialize with index = " << index;
    Incoherent<int64_t>::RW c(base_addr+index, 1);
    c[0] = value+index;
  }
};

struct randpermute_func : public ForkJoinIteration {
  GlobalAddress<int64_t> array;
  int64_t nelem;
  mrg_state st;
  void operator()(thread * me, int64_t index) {
    int64_t k = index;
    int64_t place;
//    elt_type Ak, Aplace;
//    Ak = take (&array[k]);
    Incoherent<int64_t>::RW Ak(array+k, 1);

    mrg_skip(&st, 1, k, 0);

    place = k + (int64_t)floor( mrg_get_double_orig(&st) * (nelem - k) );
    if (k != place) {
      assert (place > k);
      assert (place < nelem);
//      Aplace = take (&array[place]);
      Incoherent<int64_t>::RW Aplace(array+place, 1);
//      {
//        int64_t t;
//        t = array[place];
//        array[place] = array[k];
//        array[k] = t;
//      }
//      {
//        elt_type t;
//        t = Aplace;
//        Aplace = Ak;
//        Ak = t;
//      }
//      release (&array[place], Aplace);
    }
//    release (&array[k], Ak);
  }
};

// temporarily just do it serially on one node rather than doing parallel swaps
template<typename T>
static void randpermute(GlobalAddress<T> array, int64_t nelem, mrg_state * restrict st) {
//  typename Incoherent<T>::RW carray(array, nelem);

  for (int64_t k=0; k < nelem; k++) {
    mrg_state new_st = *st;
    int64_t which = k % SoftXMT_nodes();
    mrg_skip(&new_st, 1, k*(which+1), 0);
    int64_t place = k + (int64_t)floor( mrg_get_double_orig(&new_st) * (nelem - k) );

    typename Incoherent<T>::RW c_this(array+k, 1);
    typename Incoherent<T>::RW c_place(array+place, 1);

    // swap
    T t;
    t = *c_place;
    *c_place = *c_this;
    *c_this = t;
  }
}

struct write_edge_func : public ForkJoinIteration {
  GlobalAddress<int64_t> newlabel;
  GlobalAddress<packed_edge> ij;
  int64_t nedge;
  void operator()(thread * me, int64_t index) {
    Incoherent<packed_edge>::RW edge(ij+index, 1);
    int64_t v0 = (*edge).v0;
    int64_t v1 = (*edge).v1;
    packed_edge new_edge;
    new_edge.v0 = SoftXMT_delegate_read_word(newlabel+v0);
    new_edge.v1 = SoftXMT_delegate_read_word(newlabel+v1);
    *edge = new_edge;
  }
};

static void permute_vertex_labels (GlobalAddress<packed_edge> ij, int64_t nedge, int64_t max_nvtx, mrg_state * restrict st, GlobalAddress<int64_t> newlabel) {

//  OMP("omp for")
//	for (k = 0; k < max_nvtx; ++k)
//		newlabel[k] = k;
  {
    func_initialize f;
      f.base_addr = newlabel;
      f.value = 0.0;
    fork_join(current_thread, &f, 0, max_nvtx);
  }

  //	randpermute(newlabel, max_nvtx, st);
//	{
//    randpermute_func f;
//      f.array = newlabel;
//      f.nelem = max_nvtx;
//      f.st = *st;
//    fork_join(current_thread, &f, 0, max_nvtx);
//  }
  randpermute(newlabel, max_nvtx, st); // TODO: doing this serially for now...

  VLOG(1) << "done: randpermute";

//	OMP("omp for")
//	for (k = 0; k < nedge; ++k)
//		write_edge(&IJ[k],
//               newlabel[get_v0_from_edge(&IJ[k])],
//               newlabel[get_v1_from_edge(&IJ[k])]);
  {
    write_edge_func f;
      f.newlabel = newlabel;
      f.ij = ij;
    fork_join(current_thread, &f, 0, nedge);
  }
}

static void rmat_edge(packed_edge *out, int SCALE, double A, double B, double C, double D, const double *rn) {
	size_t rni = 0;
	int64_t i = 0, j = 0;
	int64_t bit = ((int64_t)1) << (SCALE-1);

	while (1) {
		const double r = rn[rni++];
		if (r > A) { /* outside quadrant 1 */
			if (r <= A + B) /* in quadrant 2 */
				j |= bit;
			else if (r <= A + B + C) /* in quadrant 3 */
				i |= bit;
			else { /* in quadrant 4 */
				j |= bit;
				i |= bit;
			}
		}
		if (1 == bit) break;

		/*
		 Assuming R is in (0, 1), 0.95 + 0.1 * R is in (0.95, 1.05).
		 So the new probabilities are *not* the old +/- 10% but
		 instead the old +/- 5%.
		 */
		A *= 0.95 + rn[rni++]/10;
		B *= 0.95 + rn[rni++]/10;
		C *= 0.95 + rn[rni++]/10;
		D *= 0.95 + rn[rni++]/10;
		/* Used 5 random numbers. */

		{
			const double norm = 1.0 / (A + B + C + D);
			A *= norm; B *= norm; C *= norm;
		}
		/* So long as +/- are monotonic, ensure a+b+c+d <= 1.0 */
		D = 1.0 - (A + B + C);

		bit >>= 1;
	}
	/* Iterates SCALE times. */
	write_edge(out, i, j);
}

struct random_edges_functor : public ForkJoinIteration {
  GlobalAddress<packed_edge> ij;
  GlobalAddress<int64_t> iwork;
  int64_t nedge;
  mrg_state * prng_state;
  int SCALE;
  void operator()(thread * me, int64_t index) {
    double * restrict Rlocal = (double*)alloca(NRAND(1) * sizeof(double));
    mrg_skip(prng_state, 1, NRAND(1), 0);
    for (int64_t i=0; i < NRAND(1); i++) {
      Rlocal[i] = mrg_get_double_orig(prng_state);
    }
    packed_edge new_edge;
    rmat_edge(&new_edge, this->SCALE, A, B, C, D, Rlocal);

    Incoherent<packed_edge>::RW cedge(ij+index, 1);
    *cedge = new_edge;
  }
};

struct random_edges_node_work : public ForkJoinIteration {
  mrg_state local_prng_state;
  GlobalAddress<packed_edge> edges;
  GlobalAddress<int64_t> iwork;
  int64_t nedge;
  int64_t SCALE;
  void operator()(thread * me, int64_t mynode) {
    range_t myblock = blockDist(0, nedge, mynode, SoftXMT_nodes());
    random_edges_functor f;
    f.ij = edges;
    f.iwork = iwork;
    f.nedge = nedge;
    f.prng_state = &local_prng_state;
    f.SCALE = SCALE;
    fork_join_onenode(me, &f, myblock.start, myblock.end);
  }
};

static void rmat_edgelist(tuple_graph* grin, int SCALE) {
  int64_t NV = 1L<<SCALE;
  GlobalAddress<int64_t> iwork = SoftXMT_typed_malloc<int64_t>(NV);

  {
    random_edges_node_work f;
      f.edges = grin->edges;
      f.iwork = iwork;
      f.nedge = grin->nedge;
      f.local_prng_state = prng_state_store;
      f.SCALE = SCALE;
    fork_join_custom(current_thread, &f);
  }
  VLOG(1) << "done: random_edges forkjoin";

  mrg_skip(&prng_state_store, 1, NRAND(grin->nedge), 0);

  permute_vertex_labels(grin->edges, grin->nedge, NV, &prng_state_store, iwork);

  VLOG(1) << "done: permute_vertex_labels";

  mrg_skip(&prng_state_store, 1, NV, 0);

  randpermute(grin->edges, grin->nedge, &prng_state_store);
}

static void user_main(thread * me, void * args) {
  uint64_t seed1 = 2, seed2 = 3;

  tuple_graph tg;
  tg.nedge = (int64_t)(edgefactor) << SCALE;
  tg.edges = SoftXMT_typed_malloc<packed_edge>(tg.nedge);

  int64_t NV = (int64_t)(1) << SCALE;

  /* Make the raw graph edges. */
  /* Get roots for BFS runs, plus maximum vertex with non-zero degree (used by
   * validator). */
  int num_bfs_roots = 64;
  //  int64_t* bfs_roots = (int64_t*)xmalloc(num_bfs_roots * sizeof(int64_t));
  GlobalAddress<int64_t> bfs_roots = SoftXMT_typed_malloc<int64_t>(num_bfs_roots);
  int64_t max_used_vertex = 0;

  double start, stop;
  start = timer();
  {
    /* Spread the two 64-bit numbers into five nonzero values in the correct
     * range. */
    uint_fast32_t seed[5];
    make_mrg_seed(seed1, seed2, seed);
    mrg_seed(&prng_state_store, seed);

    /* As the graph is being generated, also keep a bitmap of vertices with
     * incident edges.  We keep a grid of processes, each row of which has a
     * separate copy of the bitmap (distributed among the processes in the
     * row), and then do an allreduce at the end.  This scheme is used to avoid
     * non-local communication and reading the file separately just to find BFS
     * roots. */

    rmat_edgelist(&tg, SCALE);

    //debug: verify that rmat edgelist is valid
    for (int64_t i=0; i<tg.nedge; i++) {
      Incoherent<packed_edge>::RO e(tg.edges+i, 1);
      VLOG(1) << "edge[" << i << "] = " << (*e).v0 << " -> " << (*e).v1;
    }

    int64_t degree[NV];
    for (int64_t i=0; i<NV; i++) degree[i] = 0;

    for (int64_t i=0; i<tg.nedge; i++) {
      Incoherent<packed_edge>::RO e(tg.edges+i, 1);
      assert(e[0].v0 < NV);
      assert(e[0].v1 < NV);
      degree[e[0].v0]++;
    }
    for (int64_t i=0; i<NV; i++) {
      VLOG(1) << "degree[" << i << "] = " << degree[i];
    }

    //TODO
  }
  stop = timer();
  double make_graph_time = stop - start;
  fprintf(stderr, "graph_generation:               %f s\n", make_graph_time);

  SoftXMT_free(bfs_roots);
//  free_graph_data_structure();

  SoftXMT_free(tg.edges);

  SoftXMT_signal_done();
}

int main(int argc, char** argv) {
  SoftXMT_init(&argc, &argv, 1<<(MAX_SCALE+2));
  SoftXMT_activate();

  Node rank = SoftXMT_mynode();

  /* Parse arguments. */
  SCALE = 16;
  edgefactor = 16; /* nedges / nvertices, i.e., 2*avg. degree */
  if (argc >= 2) SCALE = atoi(argv[1]);
  if (argc >= 3) edgefactor = atoi(argv[2]);
  if (argc <= 1 || argc >= 4 || SCALE == 0 || edgefactor == 0) {
    if (rank == 0) {
      fprintf(stderr, "Usage: %s SCALE edgefactor\n  SCALE = log_2(# vertices) [integer, required]\n  edgefactor = (# edges) / (# vertices) = .5 * (average vertex degree) [integer, defaults to 16]\n(Random number seed and Kronecker initiator are in main.c)\n", argv[0]);
    }
    exit(0);
  }
  assert(SCALE <= MAX_SCALE);

  SoftXMT_run_user_main(&user_main, NULL);

  /* Print results. */

  SoftXMT_finish(0);
  return 0;
}

static void get_statistics(const double x[], int n, double r[s_LAST]) {
  double temp;
  int i;
  /* Compute mean. */
  temp = 0;
  for (i = 0; i < n; ++i) temp += x[i];
  temp /= n;
  r[s_mean] = temp;
  /* Compute std. dev. */
  temp = 0;
  for (i = 0; i < n; ++i) temp += (x[i] - r[s_mean]) * (x[i] - r[s_mean]);
  temp /= n - 1;
  r[s_std] = sqrt(temp);
  /* Sort x. */
  double* xx = (double*)xmalloc(n * sizeof(double));
  memcpy(xx, x, n * sizeof(double));
  qsort(xx, n, sizeof(double), compare_doubles);
  /* Get order statistics. */
  r[s_minimum] = xx[0];
  r[s_firstquartile] = (xx[(n - 1) / 4] + xx[n / 4]) * .5;
  r[s_median] = (xx[(n - 1) / 2] + xx[n / 2]) * .5;
  r[s_thirdquartile] = (xx[n - 1 - (n - 1) / 4] + xx[n - 1 - n / 4]) * .5;
  r[s_maximum] = xx[n - 1];
  /* Clean up. */
  free(xx);
}

<|endoftext|>


<commit_before>#include "FImage.h"

using namespace FImage;

Expr lerp(Expr a, Expr b, Expr alpha) {
    return (1.0f - alpha)*a + alpha*b;
}

int main(int argc, char **argv) {
    UniformImage input(Float(32), 2);
    Uniform<float> r_sigma;
    Uniform<int> s_sigma;
    Var x("x"), y("y"), z("z"), c("c");

    // Add a boundary condition
    Func clamped("clamped");
    clamped(x, y) = input(clamp(x, 0, input.width()),
                          clamp(y, 0, input.height()));

    // Construct the bilateral grid
    RVar i(0, s_sigma, "i"), j(0, s_sigma, "j");
    Expr val = clamped(x * s_sigma + i - s_sigma/2, y * s_sigma + j - s_sigma/2);
    val = clamp(val, 0.0f, 1.0f);
    Expr zi = cast<int>(val * (1.0f/r_sigma) + 0.5f);
    Func grid("grid");
    grid(x, y, zi, c) += select(c == 0, val, 1.0f);

    // Blur the grid using a five-tap filter
    Func blurx("blurx"), blury("blury"), blurz("blurz");
    blurx(x, y, z) = grid(x-2, y, z) + grid(x-1, y, z)*4 + grid(x, y, z)*6 + grid(x+1, y, z)*4 + grid(x+1, y, z);
    blury(x, y, z) = blurx(x, y-2, z) + blurx(x, y-1, z)*4 + blurx(x, y, z)*6 + blurx(x, y+1, z)*4 + blurx(x, y+2, z);
    blurz(x, y, z) = blury(x, y, z-2) + blury(x, y, z-1)*4 + blury(x, y, z)*6 + blury(x, y, z+1)*4 + blury(x, y, z+2);

    // Take trilinear samples to compute the output
    val = clamp(clamped(x, y), 0.0f, 1.0f);
    Expr zv = val * (1.0f/r_sigma);
    zi = cast<int>(zv);
    Expr zf = zv - zi;
    Expr xf = cast<float>(x % s_sigma) / s_sigma;
    Expr yf = cast<float>(y % s_sigma) / s_sigma;
    Expr xi = x/s_sigma;
    Expr yi = y/s_sigma;
    Func interpolated("interpolated");
    interpolated(x, y) =
        lerp(lerp(lerp(blurz(xi, yi, zi), blurz(xi+1, yi, zi), xf),
                  lerp(blurz(xi, yi+1, zi), blurz(xi+1, yi+1, zi), xf), yf),
             lerp(lerp(blurz(xi, yi, zi+1), blurz(xi+1, yi, zi+1), xf),
                  lerp(blurz(xi, yi+1, zi+1), blurz(xi+1, yi+1, zi+1), xf), yf), zf);

    // Normalize
    Func smoothed("smoothed");
    smoothed(x, y) = interpolated(x, y, 0)/interpolated(x, y, 1);

    grid.root().parallel(z);
    grid.update().transpose(y, c).transpose(x, c).transpose(i, c).transpose(j, c).parallel(y);
    blurx.root().parallel(z).vectorize(x, 4);
    blury.root().parallel(z).vectorize(x, 4);
    blurz.root().parallel(z).vectorize(x, 4);
    smoothed.root().parallel(y).vectorize(x, 4);

    smoothed.compileToFile("bilateral_grid");

    // Compared to Sylvain Paris' implementation from his webpage (on
    // which this is based), for filter params s_sigma 0.1, on a 4 megapixel
    // input, on a four core x86 (2 socket core2 mac pro)
    // Filter s_sigma: 2      4       8       16      32
    // Paris (ms):     5350   1345    472     245     184
    // Us (ms):        383    142     77      62      65
    // Speedup:        14     9.5     6.1     3.9     2.8

    // Our schedule and inlining are roughly the same as his, so the
    // gain is all down to vectorizing and parallelizing. In general
    // for larger blurs our win shrinks to roughly the number of
    // cores, as the stages we don't vectorize as well dominate (we
    // don't vectorize them well because they do gathers and scatters,
    // which don't work well on x86).  For smaller blurs, our win
    // grows, because the stages that we vectorize take up all the
    // time.

    return 0;
}

<commit_msg>Removed explicit naming from bilateral grid<commit_after>#include "FImage.h"

using namespace FImage;

Expr lerp(Expr a, Expr b, Expr alpha) {
    return (1.0f - alpha)*a + alpha*b;
}

int main(int argc, char **argv) {
    UniformImage input(Float(32), 2);
    Uniform<float> r_sigma;
    Uniform<int> s_sigma;
    Var x, y, z, c;

    // Add a boundary condition
    Func clamped;
    clamped(x, y) = input(clamp(x, 0, input.width()),
                          clamp(y, 0, input.height()));

    // Construct the bilateral grid
    RVar i(0, s_sigma), j(0, s_sigma);
    Expr val = clamped(x * s_sigma + i - s_sigma/2, y * s_sigma + j - s_sigma/2);
    val = clamp(val, 0.0f, 1.0f);
    Expr zi = cast<int>(val * (1.0f/r_sigma) + 0.5f);
    Func grid;
    grid(x, y, zi, c) += select(c == 0, val, 1.0f);

    // Blur the grid using a five-tap filter
    Func blurx, blury, blurz;
    blurx(x, y, z) = grid(x-2, y, z) + grid(x-1, y, z)*4 + grid(x, y, z)*6 + grid(x+1, y, z)*4 + grid(x+1, y, z);
    blury(x, y, z) = blurx(x, y-2, z) + blurx(x, y-1, z)*4 + blurx(x, y, z)*6 + blurx(x, y+1, z)*4 + blurx(x, y+2, z);
    blurz(x, y, z) = blury(x, y, z-2) + blury(x, y, z-1)*4 + blury(x, y, z)*6 + blury(x, y, z+1)*4 + blury(x, y, z+2);

    // Take trilinear samples to compute the output
    val = clamp(clamped(x, y), 0.0f, 1.0f);
    Expr zv = val * (1.0f/r_sigma);
    zi = cast<int>(zv);
    Expr zf = zv - zi;
    Expr xf = cast<float>(x % s_sigma) / s_sigma;
    Expr yf = cast<float>(y % s_sigma) / s_sigma;
    Expr xi = x/s_sigma;
    Expr yi = y/s_sigma;
    Func interpolated;
    interpolated(x, y) =
        lerp(lerp(lerp(blurz(xi, yi, zi), blurz(xi+1, yi, zi), xf),
                  lerp(blurz(xi, yi+1, zi), blurz(xi+1, yi+1, zi), xf), yf),
             lerp(lerp(blurz(xi, yi, zi+1), blurz(xi+1, yi, zi+1), xf),
                  lerp(blurz(xi, yi+1, zi+1), blurz(xi+1, yi+1, zi+1), xf), yf), zf);

    // Normalize
    Func smoothed;
    smoothed(x, y) = interpolated(x, y, 0)/interpolated(x, y, 1);

    grid.root().parallel(z);
    grid.update().transpose(y, c).transpose(x, c).transpose(i, c).transpose(j, c).parallel(y);
    blurx.root().parallel(z).vectorize(x, 4);
    blury.root().parallel(z).vectorize(x, 4);
    blurz.root().parallel(z).vectorize(x, 4);
    smoothed.root().parallel(y).vectorize(x, 4);

    smoothed.compileToFile("bilateral_grid");

    // Compared to Sylvain Paris' implementation from his webpage (on
    // which this is based), for filter params s_sigma 0.1, on a 4 megapixel
    // input, on a four core x86 (2 socket core2 mac pro)
    // Filter s_sigma: 2      4       8       16      32
    // Paris (ms):     5350   1345    472     245     184
    // Us (ms):        383    142     77      62      65
    // Speedup:        14     9.5     6.1     3.9     2.8

    // Our schedule and inlining are roughly the same as his, so the
    // gain is all down to vectorizing and parallelizing. In general
    // for larger blurs our win shrinks to roughly the number of
    // cores, as the stages we don't vectorize as well dominate (we
    // don't vectorize them well because they do gathers and scatters,
    // which don't work well on x86).  For smaller blurs, our win
    // grows, because the stages that we vectorize take up all the
    // time.

    return 0;
}

<|endoftext|>


<commit_before>/**
 * Copyright (c) 2016 DeepCortex GmbH <legal@eventql.io>
 * Authors:
 *   - Paul Asmuth <paul@eventql.io>
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License ("the license") as
 * published by the Free Software Foundation, either version 3 of the License,
 * or any later version.
 *
 * In accordance with Section 7(e) of the license, the licensing of the Program
 * under the license does not imply a trademark license. Therefore any rights,
 * title and interest in our trademarks remain entirely with us.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the license for more details.
 *
 * You can be released from the requirements of the license by purchasing a
 * commercial license. Buying such a license is mandatory as soon as you develop
 * commercial activities involving this program without disclosing the source
 * code of your own applications
 */
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <regex>
#include <sys/time.h>
#include <sys/resource.h>
#include "eventql/eventql.h"
#include "eventql/util/application.h"
#include "eventql/util/logging.h"
#include "eventql/util/cli/flagparser.h"
#include "eventql/util/io/FileLock.h"
#include "eventql/util/io/fileutil.h"

int main(int argc, const char** argv) {
  Application::init();
  cli::FlagParser flags;

  flags.defineFlag(
      "help",
      cli::FlagParser::T_SWITCH,
      false,
      "?",
      NULL,
      "help",
      "<help>");

  flags.defineFlag(
      "version",
      cli::FlagParser::T_SWITCH,
      false,
      "V",
      NULL,
      "print version",
      "<switch>");

  flags.defineFlag(
      "config",
      ::cli::FlagParser::T_STRING,
      false,
      "c",
      NULL,
      "path to config file",
      "<config_file>");

  flags.defineFlag(
      "config_set",
      ::cli::FlagParser::T_STRING,
      false,
      "C",
      NULL,
      "set config option",
      "<key>=<val>");

  flags.defineFlag(
      "standalone",
      cli::FlagParser::T_SWITCH,
      false,
      NULL,
      NULL,
      "standalone mode",
      "<switch>");

  flags.defineFlag(
      "listen",
      cli::FlagParser::T_STRING,
      false,
      NULL,
      NULL,
      "listen",
      "<host:port>");

  flags.defineFlag(
      "datadir",
      cli::FlagParser::T_STRING,
      false,
      NULL,
      NULL,
      "datadir path",
      "<path>");

  flags.defineFlag(
      "loglevel",
      cli::FlagParser::T_STRING,
      false,
      NULL,
      "INFO",
      "loglevel",
      "<level>");

  flags.defineFlag(
      "daemonize",
      cli::FlagParser::T_SWITCH,
      false,
      NULL,
      NULL,
      "daemonize",
      "<switch>");

  flags.defineFlag(
      "pidfile",
      cli::FlagParser::T_STRING,
      false,
      NULL,
      NULL,
      "pidfile",
      "<path>");

  flags.defineFlag(
      "log_to_syslog",
      cli::FlagParser::T_SWITCH,
      false,
      NULL,
      NULL,
      "log to syslog",
      "<switch>");

  flags.defineFlag(
      "nolog_to_stderr",
      cli::FlagParser::T_SWITCH,
      false,
      NULL,
      NULL,
      "don't log to stderr",
      "<switch>");

  flags.parseArgv(argc, argv);

  if (!flags.isSet("nolog_to_stderr") && !flags.isSet("daemonize")) {
    Application::logToStderr("evqld");
  }

  if (flags.isSet("log_to_syslog")) {
    Application::logToSyslog("evqld");
  }

  Logger::get()->setMinimumLogLevel(
      strToLogLevel(flags.getString("loglevel")));

  /* print help */
  if (flags.isSet("help") || flags.isSet("version")) {
#ifdef EVQL_VERSION
    static const std::string version = EVQL_VERSION;
#else
    static const std::string version = "unknown";
#endif

#ifdef EVQL_BUILDID
    static const std::string build_id = EVQL_BUILDID;
#else
    static const std::string build_id = "unknown";
#endif

    auto stdout_os = OutputStream::getStdout();
    stdout_os->write(
        StringUtil::format(
            "EventQL $0 ($1)\n"
            "Copyright (c) 2016, DeepCortex GmbH. All rights reserved.\n\n",
            version,
            build_id));
  }

  if (flags.isSet("version")) {
    return 0;
  }

  if (flags.isSet("help")) {
    auto stdout_os = OutputStream::getStdout();
    stdout_os->write(
        "Usage: $ evqld [OPTIONS]\n\n"
        "   -c, --config <file>       Load config from file\n"
        "   -C name=value             Define a config value on the command line\n"
        "   --standalone              Run in standalone mode\n"
        "   --datadir <path>          Path to data directory\n"
        "   --listen <host:port>      Listen on this address (default: localhost:9175)\n"
        "   --daemonize               Daemonize the server\n"
        "   --pidfile <file>          Write a PID file\n"
        "   --loglevel <level>        Minimum log level (default: INFO)\n"
        "   --[no]log_to_syslog       Do[n't] log to syslog\n"
        "   --[no]log_to_stderr       Do[n't] log to stderr\n"
        "   -?, --help                Display this help text and exit\n"
        "   -v, --version             Display the version of this binary and exit\n"
        "                                                       \n"
        "Examples:                                              \n"
        "   $ evqld --standalone --datadir /var/evql\n"
        "   $ evqld -c /etc/evqld.conf --daemonize --pidfile /run/evql.pid\n"
    );
    return 0;
  }

  /* conf */
  auto conf = evql_conf_init();
  if (!conf) {
    logFatal("evqld", "error while initializing EventQL server");
    return 1;
  }

  evql_conf_set(conf, "cluster.rebalance_interval", "60000000");
  evql_conf_set(conf, "cluster.allowed_hosts", "");
  evql_conf_set(conf, "server.listen", "localhost:9175");
  evql_conf_set(conf, "server.indexbuild_threads", "2");
  evql_conf_set(conf, "server.gc_mode", "AUTOMATIC");
  evql_conf_set(conf, "server.gc_interval", "30000000");
  evql_conf_set(conf, "server.cachedir_maxsize", "68719476736");
  evql_conf_set(conf, "server.noleader", "false");
  evql_conf_set(conf, "server.c2s_io_timeout", "1000000");
  evql_conf_set(conf, "server.c2s_idle_timeout", "1800000000");
  evql_conf_set(conf, "server.s2s_io_timeout", "1000000");
  evql_conf_set(conf, "server.s2s_idle_timeout", "5000000");
  evql_conf_set(conf, "server.http_io_timeout", "1000000");
  evql_conf_set(conf, "server.heartbeat_interval", "1000000");
  evql_conf_set(conf, "server.query_progress_rate_limit", "250000");

  if (flags.isSet("standalone")) {
    evql_conf_set(conf, "cluster.coordinator", "standalone");
    evql_conf_set(conf, "cluster.allowed_hosts", "0.0.0.0/0");
    evql_conf_set(conf, "server.name", "standalone");
    evql_conf_set(conf, "server.client_auth_backend", "trust");
    evql_conf_set(conf, "server.noleader", "true");
  }

  if (flags.isSet("config")) {
    auto config_file_path = flags.getString("config");
    int rc = evql_conf_load(
        conf,
        config_file_path.empty() ? nullptr : config_file_path.c_str());

    if (rc) {
      logFatal(
          "evqld",
          "error while loading config file");

      evql_conf_free(conf);
      return 1;
    }
  }

  for (const auto& opt : flags.getStrings("config_set")) {
    auto opt_key_end = opt.find("=");
    if (opt_key_end == String::npos) {
      logFatal("invalid config option: $0", opt);
      evql_conf_free(conf);
      return 1;
    }

    auto opt_key = opt.substr(0, opt_key_end);
    auto opt_value = opt.substr(opt_key_end + 1);
    evql_conf_set(conf, opt_key.c_str(), opt_value.c_str());
  }

  if (flags.isSet("listen")) {
    auto listen = flags.getString("listen");
    evql_conf_set(conf, "server.listen", listen.c_str());
  }

  if (flags.isSet("datadir")) {
    auto datadir = flags.getString("datadir");
    evql_conf_set(conf, "server.datadir", datadir.c_str());
  }

  if (flags.isSet("daemonize")) {
    evql_conf_set(conf, "server.daemonize", "true");
  }

  if (flags.isSet("pidfile")) {
    auto pidfile = flags.getString("pidfile");
    evql_conf_set(conf, "server.pidfile", pidfile.c_str());
  }

  /* init server */
  auto server = evql_server_init(conf);
  if (!server) {
    logFatal("evqld", "error while initializing EventQL server");
    evql_conf_free(conf);
    return 1;
  }

  if (!evql_server_getconf(server, "server.datadir")) {
    logFatal("evqld", "missing 'server.datadir' option or --datadir flag");
    evql_server_free(server);
    evql_conf_free(conf);
    return 1;
  }

  /* daemonize */
  if (evql_server_getconfbool(server, "server.daemonize")) {
    Application::daemonize();
  }

  /* pidfile */
  ScopedPtr<FileLock> pidfile_lock;
  String pidfile_path;
  {
    auto pidfile_path_cstr = evql_server_getconf(server, "server.pidfile");
    if (pidfile_path_cstr) {
      pidfile_path = std::string(pidfile_path_cstr);
    }
  }

  if (!pidfile_path.empty()) {
    pidfile_lock = mkScoped(new FileLock(pidfile_path));
    pidfile_lock->lock(false);

    auto pidfile = File::openFile(
        pidfile_path,
        File::O_WRITE | File::O_CREATEOROPEN | File::O_TRUNCATE);

    pidfile.write(StringUtil::toString(getpid()));
  }

  /* start database */
  int rc = evql_server_start(server);
  if (!rc) {
    rc = evql_server_listen(server, -1);
  }

  if (rc) {
    logAlert("eventql", "FATAL ERROR: $0", evql_server_geterror(server));
  }

  /* shutdown */
  logInfo("eventql", "Exiting...");
  evql_server_shutdown(server);

  if (pidfile_lock.get()) {
    pidfile_lock.reset(nullptr);
    FileUtil::rm(pidfile_path);
  }

  evql_server_free(server);
  evql_conf_free(conf);

  return rc;
}

<commit_msg>set cluster.allow_anonymous to true<commit_after>/**
 * Copyright (c) 2016 DeepCortex GmbH <legal@eventql.io>
 * Authors:
 *   - Paul Asmuth <paul@eventql.io>
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License ("the license") as
 * published by the Free Software Foundation, either version 3 of the License,
 * or any later version.
 *
 * In accordance with Section 7(e) of the license, the licensing of the Program
 * under the license does not imply a trademark license. Therefore any rights,
 * title and interest in our trademarks remain entirely with us.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the license for more details.
 *
 * You can be released from the requirements of the license by purchasing a
 * commercial license. Buying such a license is mandatory as soon as you develop
 * commercial activities involving this program without disclosing the source
 * code of your own applications
 */
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <regex>
#include <sys/time.h>
#include <sys/resource.h>
#include "eventql/eventql.h"
#include "eventql/util/application.h"
#include "eventql/util/logging.h"
#include "eventql/util/cli/flagparser.h"
#include "eventql/util/io/FileLock.h"
#include "eventql/util/io/fileutil.h"

int main(int argc, const char** argv) {
  Application::init();
  cli::FlagParser flags;

  flags.defineFlag(
      "help",
      cli::FlagParser::T_SWITCH,
      false,
      "?",
      NULL,
      "help",
      "<help>");

  flags.defineFlag(
      "version",
      cli::FlagParser::T_SWITCH,
      false,
      "V",
      NULL,
      "print version",
      "<switch>");

  flags.defineFlag(
      "config",
      ::cli::FlagParser::T_STRING,
      false,
      "c",
      NULL,
      "path to config file",
      "<config_file>");

  flags.defineFlag(
      "config_set",
      ::cli::FlagParser::T_STRING,
      false,
      "C",
      NULL,
      "set config option",
      "<key>=<val>");

  flags.defineFlag(
      "standalone",
      cli::FlagParser::T_SWITCH,
      false,
      NULL,
      NULL,
      "standalone mode",
      "<switch>");

  flags.defineFlag(
      "listen",
      cli::FlagParser::T_STRING,
      false,
      NULL,
      NULL,
      "listen",
      "<host:port>");

  flags.defineFlag(
      "datadir",
      cli::FlagParser::T_STRING,
      false,
      NULL,
      NULL,
      "datadir path",
      "<path>");

  flags.defineFlag(
      "loglevel",
      cli::FlagParser::T_STRING,
      false,
      NULL,
      "INFO",
      "loglevel",
      "<level>");

  flags.defineFlag(
      "daemonize",
      cli::FlagParser::T_SWITCH,
      false,
      NULL,
      NULL,
      "daemonize",
      "<switch>");

  flags.defineFlag(
      "pidfile",
      cli::FlagParser::T_STRING,
      false,
      NULL,
      NULL,
      "pidfile",
      "<path>");

  flags.defineFlag(
      "log_to_syslog",
      cli::FlagParser::T_SWITCH,
      false,
      NULL,
      NULL,
      "log to syslog",
      "<switch>");

  flags.defineFlag(
      "nolog_to_stderr",
      cli::FlagParser::T_SWITCH,
      false,
      NULL,
      NULL,
      "don't log to stderr",
      "<switch>");

  flags.parseArgv(argc, argv);

  if (!flags.isSet("nolog_to_stderr") && !flags.isSet("daemonize")) {
    Application::logToStderr("evqld");
  }

  if (flags.isSet("log_to_syslog")) {
    Application::logToSyslog("evqld");
  }

  Logger::get()->setMinimumLogLevel(
      strToLogLevel(flags.getString("loglevel")));

  /* print help */
  if (flags.isSet("help") || flags.isSet("version")) {
#ifdef EVQL_VERSION
    static const std::string version = EVQL_VERSION;
#else
    static const std::string version = "unknown";
#endif

#ifdef EVQL_BUILDID
    static const std::string build_id = EVQL_BUILDID;
#else
    static const std::string build_id = "unknown";
#endif

    auto stdout_os = OutputStream::getStdout();
    stdout_os->write(
        StringUtil::format(
            "EventQL $0 ($1)\n"
            "Copyright (c) 2016, DeepCortex GmbH. All rights reserved.\n\n",
            version,
            build_id));
  }

  if (flags.isSet("version")) {
    return 0;
  }

  if (flags.isSet("help")) {
    auto stdout_os = OutputStream::getStdout();
    stdout_os->write(
        "Usage: $ evqld [OPTIONS]\n\n"
        "   -c, --config <file>       Load config from file\n"
        "   -C name=value             Define a config value on the command line\n"
        "   --standalone              Run in standalone mode\n"
        "   --datadir <path>          Path to data directory\n"
        "   --listen <host:port>      Listen on this address (default: localhost:9175)\n"
        "   --daemonize               Daemonize the server\n"
        "   --pidfile <file>          Write a PID file\n"
        "   --loglevel <level>        Minimum log level (default: INFO)\n"
        "   --[no]log_to_syslog       Do[n't] log to syslog\n"
        "   --[no]log_to_stderr       Do[n't] log to stderr\n"
        "   -?, --help                Display this help text and exit\n"
        "   -v, --version             Display the version of this binary and exit\n"
        "                                                       \n"
        "Examples:                                              \n"
        "   $ evqld --standalone --datadir /var/evql\n"
        "   $ evqld -c /etc/evqld.conf --daemonize --pidfile /run/evql.pid\n"
    );
    return 0;
  }

  /* conf */
  auto conf = evql_conf_init();
  if (!conf) {
    logFatal("evqld", "error while initializing EventQL server");
    return 1;
  }

  evql_conf_set(conf, "cluster.rebalance_interval", "60000000");
  evql_conf_set(conf, "cluster.allowed_hosts", "");
  evql_conf_set(conf, "cluster.allow_anonymous", "true");
  evql_conf_set(conf, "server.listen", "localhost:9175");
  evql_conf_set(conf, "server.indexbuild_threads", "2");
  evql_conf_set(conf, "server.gc_mode", "AUTOMATIC");
  evql_conf_set(conf, "server.gc_interval", "30000000");
  evql_conf_set(conf, "server.cachedir_maxsize", "68719476736");
  evql_conf_set(conf, "server.noleader", "false");
  evql_conf_set(conf, "server.c2s_io_timeout", "1000000");
  evql_conf_set(conf, "server.c2s_idle_timeout", "1800000000");
  evql_conf_set(conf, "server.s2s_io_timeout", "1000000");
  evql_conf_set(conf, "server.s2s_idle_timeout", "5000000");
  evql_conf_set(conf, "server.http_io_timeout", "1000000");
  evql_conf_set(conf, "server.heartbeat_interval", "1000000");
  evql_conf_set(conf, "server.query_progress_rate_limit", "250000");

  if (flags.isSet("standalone")) {
    evql_conf_set(conf, "cluster.coordinator", "standalone");
    evql_conf_set(conf, "cluster.allowed_hosts", "0.0.0.0/0");
    evql_conf_set(conf, "server.name", "standalone");
    evql_conf_set(conf, "server.client_auth_backend", "trust");
    evql_conf_set(conf, "server.noleader", "true");
  }

  if (flags.isSet("config")) {
    auto config_file_path = flags.getString("config");
    int rc = evql_conf_load(
        conf,
        config_file_path.empty() ? nullptr : config_file_path.c_str());

    if (rc) {
      logFatal(
          "evqld",
          "error while loading config file");

      evql_conf_free(conf);
      return 1;
    }
  }

  for (const auto& opt : flags.getStrings("config_set")) {
    auto opt_key_end = opt.find("=");
    if (opt_key_end == String::npos) {
      logFatal("invalid config option: $0", opt);
      evql_conf_free(conf);
      return 1;
    }

    auto opt_key = opt.substr(0, opt_key_end);
    auto opt_value = opt.substr(opt_key_end + 1);
    evql_conf_set(conf, opt_key.c_str(), opt_value.c_str());
  }

  if (flags.isSet("listen")) {
    auto listen = flags.getString("listen");
    evql_conf_set(conf, "server.listen", listen.c_str());
  }

  if (flags.isSet("datadir")) {
    auto datadir = flags.getString("datadir");
    evql_conf_set(conf, "server.datadir", datadir.c_str());
  }

  if (flags.isSet("daemonize")) {
    evql_conf_set(conf, "server.daemonize", "true");
  }

  if (flags.isSet("pidfile")) {
    auto pidfile = flags.getString("pidfile");
    evql_conf_set(conf, "server.pidfile", pidfile.c_str());
  }

  /* init server */
  auto server = evql_server_init(conf);
  if (!server) {
    logFatal("evqld", "error while initializing EventQL server");
    evql_conf_free(conf);
    return 1;
  }

  if (!evql_server_getconf(server, "server.datadir")) {
    logFatal("evqld", "missing 'server.datadir' option or --datadir flag");
    evql_server_free(server);
    evql_conf_free(conf);
    return 1;
  }

  /* daemonize */
  if (evql_server_getconfbool(server, "server.daemonize")) {
    Application::daemonize();
  }

  /* pidfile */
  ScopedPtr<FileLock> pidfile_lock;
  String pidfile_path;
  {
    auto pidfile_path_cstr = evql_server_getconf(server, "server.pidfile");
    if (pidfile_path_cstr) {
      pidfile_path = std::string(pidfile_path_cstr);
    }
  }

  if (!pidfile_path.empty()) {
    pidfile_lock = mkScoped(new FileLock(pidfile_path));
    pidfile_lock->lock(false);

    auto pidfile = File::openFile(
        pidfile_path,
        File::O_WRITE | File::O_CREATEOROPEN | File::O_TRUNCATE);

    pidfile.write(StringUtil::toString(getpid()));
  }

  /* start database */
  int rc = evql_server_start(server);
  if (!rc) {
    rc = evql_server_listen(server, -1);
  }

  if (rc) {
    logAlert("eventql", "FATAL ERROR: $0", evql_server_geterror(server));
  }

  /* shutdown */
  logInfo("eventql", "Exiting...");
  evql_server_shutdown(server);

  if (pidfile_lock.get()) {
    pidfile_lock.reset(nullptr);
    FileUtil::rm(pidfile_path);
  }

  evql_server_free(server);
  evql_conf_free(conf);

  return rc;
}

<|endoftext|>


<commit_before>#include <cstdio>
#include <SOIL.h>
#include <GL/glut.h>
#include "globals.h"
#include "texture.h"

//#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
//#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x8FF

//bool anisotropic_filtering;
//float max_anistropy;
/* Generates a generic texture with some parameters already set
Example usage:

GLuint wall_texture = genTexture("images/textures/wall.raw",1)
glBindTexture(GL_TEXTURE_2D,texture);
glBegin(GL_QUADS);
glTexCoord2d(0.0,0.0); glVertex2d(0.0,0.0);
glTexCoord2d(1.0,0.0); glVertex2d(1.0,0.0);
glTexCoord2d(1.0,1.0); glVertex2d(1.0,1.0);
glTexCoord2d(0.0,1.0); glVertex2d(0.0,1.0);
glEnd();

*/

/*this works with png's now yay*/
GLuint genTexture(const char *filename){
	/* load an image file directly as a new OpenGL texture */
	GLuint tex_2d = SOIL_load_OGL_texture
		(
		filename,
		SOIL_LOAD_AUTO,
		SOIL_CREATE_NEW_ID,
		SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y |
		SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT
		);

	/* check for an error during the load process */
	if( 0 == tex_2d )
	{
		printf( "SOIL loading error: '%s'\n", SOIL_last_result() );
	}
	if(anisotropic_filtering){
	  glBindTexture(GL_TEXTURE_2D,tex_2d);
	  glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,
			  max_anistropy);
	}
	return tex_2d;
}
<commit_msg>what I meant to say in the last commit is that I have anistropic  filtering working now so the walls look less blurry at a distance now.  Removing some commented lines we dont need it this commit.<commit_after>#include <cstdio>
#include <SOIL.h>
#include <GL/glut.h>
#include "globals.h"
#include "texture.h"

/* Generates a generic texture with some parameters already set
Example usage:

GLuint wall_texture = genTexture("images/textures/wall.raw",1)
glBindTexture(GL_TEXTURE_2D,texture);
glBegin(GL_QUADS);
glTexCoord2d(0.0,0.0); glVertex2d(0.0,0.0);
glTexCoord2d(1.0,0.0); glVertex2d(1.0,0.0);
glTexCoord2d(1.0,1.0); glVertex2d(1.0,1.0);
glTexCoord2d(0.0,1.0); glVertex2d(0.0,1.0);
glEnd();

*/

/*this works with png's now yay*/
GLuint genTexture(const char *filename){
	/* load an image file directly as a new OpenGL texture */
	GLuint tex_2d = SOIL_load_OGL_texture
		(
		filename,
		SOIL_LOAD_AUTO,
		SOIL_CREATE_NEW_ID,
		SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y |
		SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT
		);

	/* check for an error during the load process */
	if( 0 == tex_2d )
	{
		printf( "SOIL loading error: '%s'\n", SOIL_last_result() );
	}
	if(anisotropic_filtering){
	  glBindTexture(GL_TEXTURE_2D,tex_2d);
	  glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,
			  max_anistropy);
	}
	return tex_2d;
}
<|endoftext|>


<commit_before>/*
 Copyright (c) 2010, The Barbarian Group
 All rights reserved.

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

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

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

#include "cinder/gl/gl.h"
#include "cinder/gl/GlslProg.h"

using boost::shared_ptr;
using namespace std;

namespace cinder { namespace gl {

GlslProg::Obj::~Obj()
{
	if( mHandle )
		glDeleteProgram( (GLuint)mHandle );
}

//////////////////////////////////////////////////////////////////////////
// GlslProg
GlslProg::GlslProg( DataSourceRef vertexShader, DataSourceRef fragmentShader, DataSourceRef geometryShader )
	: mObj( shared_ptr<Obj>( new Obj ) )
{
	mObj->mHandle = glCreateProgram();

	loadShader( vertexShader->getBuffer(), GL_VERTEX_SHADER_ARB );
	if( fragmentShader )
		loadShader( fragmentShader->getBuffer(), GL_FRAGMENT_SHADER_ARB );
	if( geometryShader )
		loadShader( geometryShader->getBuffer(), GL_GEOMETRY_SHADER_EXT );

	link();
}

GlslProg::GlslProg( const char *vertexShader, const char *fragmentShader, const char *geometryShader )
	: mObj( shared_ptr<Obj>( new Obj ) )
{
	mObj->mHandle = glCreateProgram();

	loadShader( vertexShader, GL_VERTEX_SHADER_ARB );
	if( fragmentShader )
		loadShader( fragmentShader, GL_FRAGMENT_SHADER_ARB );
	if( geometryShader )
		loadShader( geometryShader, GL_GEOMETRY_SHADER_EXT );

	link();
}

void GlslProg::loadShader( Buffer shaderSourceBuffer, GLint shaderType )
{
	// we need to duplicate the contents of the buffer and append a null-terminator
	shared_ptr<char> sourceBlock( new char[shaderSourceBuffer.getDataSize() + 1], checked_array_deleter<char>() );
	memcpy( sourceBlock.get(), shaderSourceBuffer.getData(), shaderSourceBuffer.getDataSize() );
	sourceBlock.get()[shaderSourceBuffer.getDataSize()] = 0; // null terminate
	const char *sourceBlockPtr = sourceBlock.get();
	loadShader( sourceBlockPtr, shaderType );
}

void GlslProg::loadShader( const char *shaderSource, GLint shaderType )
{
	GLuint handle = glCreateShader( shaderType );
	glShaderSource( handle, 1, reinterpret_cast<const GLchar**>( &shaderSource ), NULL );
	glCompileShader( handle );

	GLint status;
	glGetShaderiv( (GLuint) handle, GL_COMPILE_STATUS, &status );
	if( status != GL_TRUE ) {
		std::string log = getShaderLog( (GLuint)handle );
		throw GlslProgCompileExc( log, shaderType );
	}
	glAttachShader( mObj->mHandle, handle );
}

void GlslProg::link()
{
	glLinkProgram( mObj->mHandle );
}

void GlslProg::bind() const
{
	glUseProgram( mObj->mHandle );
}

void GlslProg::unbind()
{
	glUseProgram( 0 );
}

std::string GlslProg::getShaderLog( GLuint handle ) const
{
	std::string log;

	GLchar *debugLog;
	GLint debugLength = 0, charsWritten = 0;
	glGetShaderiv( handle, GL_INFO_LOG_LENGTH, &debugLength );

	if( debugLength > 0 ) {
		debugLog = new GLchar[debugLength];
		glGetShaderInfoLog( handle, debugLength, &charsWritten, debugLog );
		log.append( debugLog, 0, debugLength );
		delete [] debugLog;
	}

	return log;
}

void GlslProg::uniform( const std::string &name, int data )
{
	GLint loc = getUniformLocation( name );
	glUniform1i( loc, data );
}

void GlslProg::uniform( const std::string &name, const Vec2i &data )
{
	GLint loc = getUniformLocation( name );
	glUniform2i( loc, data.x, data.y );
}

void GlslProg::uniform( const std::string &name, const int *data, int count )
{
	GLint loc = getUniformLocation( name );
	glUniform1iv( loc, count, data );
}

void GlslProg::uniform( const std::string &name, const Vec2i *data, int count )
{
	GLint loc = getUniformLocation( name );
	glUniform2iv( loc, count, &data[0].x );
}

void GlslProg::uniform( const std::string &name, float data )
{
	GLint loc = getUniformLocation( name );
	glUniform1f( loc, data );
}

void GlslProg::uniform( const std::string &name, const Vec2f &data )
{
	GLint loc = getUniformLocation( name );
	glUniform2f( loc, data.x, data.y );
}

void GlslProg::uniform( const std::string &name, const Vec3f &data )
{
	GLint loc = getUniformLocation( name );
	glUniform3f( loc, data.x, data.y, data.z );
}

void GlslProg::uniform( const std::string &name, const Vec4f &data )
{
	GLint loc = getUniformLocation( name );
	glUniform4f( loc, data.x, data.y, data.z, data.w );
}

void GlslProg::uniform( const std::string &name, const float *data, int count )
{
	GLint loc = getUniformLocation( name );
	glUniform1fv( loc, count, data );
}

void GlslProg::uniform( const std::string &name, const Vec2f *data, int count )
{
	GLint loc = getUniformLocation( name );
	glUniform2fv( loc, count, &data[0].x );
}

void GlslProg::uniform( const std::string &name, const Vec3f *data, int count )
{
	GLint loc = getUniformLocation( name );
	glUniform3fv( loc, count, &data[0].x );
}

void GlslProg::uniform( const std::string &name, const Vec4f *data, int count )
{
	GLint loc = getUniformLocation( name );
	glUniform4fv( loc, count, &data[0].x );
}

void GlslProg::uniform( const std::string &name, const Matrix44f &data, bool transpose )
{
	GLint loc = getUniformLocation( name );
	glUniformMatrix4fv( loc, 1, ( transpose ) ? GL_TRUE : GL_FALSE, data.m );
}

GLint GlslProg::getUniformLocation( const std::string &name )
{
	map<string,int>::const_iterator uniformIt = mObj->mUniformLocs.find( name );
	if( uniformIt == mObj->mUniformLocs.end() ) {
		GLint loc = glGetUniformLocation( mObj->mHandle, name.c_str() );
		mObj->mUniformLocs[name] = loc;
		return loc;
	}
	else
		return uniformIt->second;
}

GLint GlslProg::getAttribLocation( const std::string &name )
{
	return glGetAttribLocation( mObj->mHandle, name.c_str() );
}

//////////////////////////////////////////////////////////////////////////
// GlslProgCompileExc
GlslProgCompileExc::GlslProgCompileExc( const std::string &log, GLint aShaderType ) throw()
	: mShaderType( aShaderType )
{
	if( mShaderType == GL_VERTEX_SHADER_ARB )
		strncpy( mMessage, "VERTEX: ", 1000 );
	else if( mShaderType == GL_FRAGMENT_SHADER_ARB )
		strncpy( mMessage, "FRAGMENT: ", 1000 );
	else if( mShaderType == GL_GEOMETRY_SHADER_EXT )
		strncpy( mMessage, "GEOMETRY: ", 1000 );
	else
		strncpy( mMessage, "UNKNOWN: ", 1000 );
	strncat( mMessage, log.c_str(), 15000 );
}

} } // namespace cinder::gl
<commit_msg>changed GlslProg constructors to allow passing NULL for vertexShader<commit_after>/*
 Copyright (c) 2010, The Barbarian Group
 All rights reserved.

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

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

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

#include "cinder/gl/gl.h"
#include "cinder/gl/GlslProg.h"

using boost::shared_ptr;
using namespace std;

namespace cinder { namespace gl {

GlslProg::Obj::~Obj()
{
	if( mHandle )
		glDeleteProgram( (GLuint)mHandle );
}

//////////////////////////////////////////////////////////////////////////
// GlslProg
GlslProg::GlslProg( DataSourceRef vertexShader, DataSourceRef fragmentShader, DataSourceRef geometryShader )
	: mObj( shared_ptr<Obj>( new Obj ) )
{
	mObj->mHandle = glCreateProgram();

	if ( vertexShader )
		loadShader( vertexShader->getBuffer(), GL_VERTEX_SHADER_ARB );
	if( fragmentShader )
		loadShader( fragmentShader->getBuffer(), GL_FRAGMENT_SHADER_ARB );
	if( geometryShader )
		loadShader( geometryShader->getBuffer(), GL_GEOMETRY_SHADER_EXT );

	link();
}

GlslProg::GlslProg( const char *vertexShader, const char *fragmentShader, const char *geometryShader )
	: mObj( shared_ptr<Obj>( new Obj ) )
{
	mObj->mHandle = glCreateProgram();

	if ( vertexShader )
		loadShader( vertexShader, GL_VERTEX_SHADER_ARB );
	if( fragmentShader )
		loadShader( fragmentShader, GL_FRAGMENT_SHADER_ARB );
	if( geometryShader )
		loadShader( geometryShader, GL_GEOMETRY_SHADER_EXT );

	link();
}

void GlslProg::loadShader( Buffer shaderSourceBuffer, GLint shaderType )
{
	// we need to duplicate the contents of the buffer and append a null-terminator
	shared_ptr<char> sourceBlock( new char[shaderSourceBuffer.getDataSize() + 1], checked_array_deleter<char>() );
	memcpy( sourceBlock.get(), shaderSourceBuffer.getData(), shaderSourceBuffer.getDataSize() );
	sourceBlock.get()[shaderSourceBuffer.getDataSize()] = 0; // null terminate
	const char *sourceBlockPtr = sourceBlock.get();
	loadShader( sourceBlockPtr, shaderType );
}

void GlslProg::loadShader( const char *shaderSource, GLint shaderType )
{
	GLuint handle = glCreateShader( shaderType );
	glShaderSource( handle, 1, reinterpret_cast<const GLchar**>( &shaderSource ), NULL );
	glCompileShader( handle );

	GLint status;
	glGetShaderiv( (GLuint) handle, GL_COMPILE_STATUS, &status );
	if( status != GL_TRUE ) {
		std::string log = getShaderLog( (GLuint)handle );
		throw GlslProgCompileExc( log, shaderType );
	}
	glAttachShader( mObj->mHandle, handle );
}

void GlslProg::link()
{
	glLinkProgram( mObj->mHandle );
}

void GlslProg::bind() const
{
	glUseProgram( mObj->mHandle );
}

void GlslProg::unbind()
{
	glUseProgram( 0 );
}

std::string GlslProg::getShaderLog( GLuint handle ) const
{
	std::string log;

	GLchar *debugLog;
	GLint debugLength = 0, charsWritten = 0;
	glGetShaderiv( handle, GL_INFO_LOG_LENGTH, &debugLength );

	if( debugLength > 0 ) {
		debugLog = new GLchar[debugLength];
		glGetShaderInfoLog( handle, debugLength, &charsWritten, debugLog );
		log.append( debugLog, 0, debugLength );
		delete [] debugLog;
	}

	return log;
}

void GlslProg::uniform( const std::string &name, int data )
{
	GLint loc = getUniformLocation( name );
	glUniform1i( loc, data );
}

void GlslProg::uniform( const std::string &name, const Vec2i &data )
{
	GLint loc = getUniformLocation( name );
	glUniform2i( loc, data.x, data.y );
}

void GlslProg::uniform( const std::string &name, const int *data, int count )
{
	GLint loc = getUniformLocation( name );
	glUniform1iv( loc, count, data );
}

void GlslProg::uniform( const std::string &name, const Vec2i *data, int count )
{
	GLint loc = getUniformLocation( name );
	glUniform2iv( loc, count, &data[0].x );
}

void GlslProg::uniform( const std::string &name, float data )
{
	GLint loc = getUniformLocation( name );
	glUniform1f( loc, data );
}

void GlslProg::uniform( const std::string &name, const Vec2f &data )
{
	GLint loc = getUniformLocation( name );
	glUniform2f( loc, data.x, data.y );
}

void GlslProg::uniform( const std::string &name, const Vec3f &data )
{
	GLint loc = getUniformLocation( name );
	glUniform3f( loc, data.x, data.y, data.z );
}

void GlslProg::uniform( const std::string &name, const Vec4f &data )
{
	GLint loc = getUniformLocation( name );
	glUniform4f( loc, data.x, data.y, data.z, data.w );
}

void GlslProg::uniform( const std::string &name, const float *data, int count )
{
	GLint loc = getUniformLocation( name );
	glUniform1fv( loc, count, data );
}

void GlslProg::uniform( const std::string &name, const Vec2f *data, int count )
{
	GLint loc = getUniformLocation( name );
	glUniform2fv( loc, count, &data[0].x );
}

void GlslProg::uniform( const std::string &name, const Vec3f *data, int count )
{
	GLint loc = getUniformLocation( name );
	glUniform3fv( loc, count, &data[0].x );
}

void GlslProg::uniform( const std::string &name, const Vec4f *data, int count )
{
	GLint loc = getUniformLocation( name );
	glUniform4fv( loc, count, &data[0].x );
}

void GlslProg::uniform( const std::string &name, const Matrix44f &data, bool transpose )
{
	GLint loc = getUniformLocation( name );
	glUniformMatrix4fv( loc, 1, ( transpose ) ? GL_TRUE : GL_FALSE, data.m );
}

GLint GlslProg::getUniformLocation( const std::string &name )
{
	map<string,int>::const_iterator uniformIt = mObj->mUniformLocs.find( name );
	if( uniformIt == mObj->mUniformLocs.end() ) {
		GLint loc = glGetUniformLocation( mObj->mHandle, name.c_str() );
		mObj->mUniformLocs[name] = loc;
		return loc;
	}
	else
		return uniformIt->second;
}

GLint GlslProg::getAttribLocation( const std::string &name )
{
	return glGetAttribLocation( mObj->mHandle, name.c_str() );
}

//////////////////////////////////////////////////////////////////////////
// GlslProgCompileExc
GlslProgCompileExc::GlslProgCompileExc( const std::string &log, GLint aShaderType ) throw()
	: mShaderType( aShaderType )
{
	if( mShaderType == GL_VERTEX_SHADER_ARB )
		strncpy( mMessage, "VERTEX: ", 1000 );
	else if( mShaderType == GL_FRAGMENT_SHADER_ARB )
		strncpy( mMessage, "FRAGMENT: ", 1000 );
	else if( mShaderType == GL_GEOMETRY_SHADER_EXT )
		strncpy( mMessage, "GEOMETRY: ", 1000 );
	else
		strncpy( mMessage, "UNKNOWN: ", 1000 );
	strncat( mMessage, log.c_str(), 15000 );
}

} } // namespace cinder::gl
<|endoftext|>


<commit_before>/* Copyright (c) 2006, NIF File Format Library and Tools
All rights reserved.  Please see niflib.h for licence. */

#include "NiNode.h"
#include "NiAVObject.h"
#include "NiDynamicEffect.h"
#include "NiSkinInstance.h"
#include "NiSkinData.h"
#include "NiTriBasedGeom.h"
using namespace Niflib;

//Definition of TYPE constant
const Type NiNode::TYPE("NiNode", &NI_NODE_PARENT::TypeConst() );

NiNode::NiNode() NI_NODE_CONSTRUCT {}

NiNode::~NiNode() {
	//Clear Children
	ClearChildren();

	//Unbind any attached skins
	for ( list<NiSkinInstance*>::iterator it = skins.begin(); it != skins.end(); ++it ) {
		(*it)->SkeletonLost();
	}
}

void NiNode::Read( istream& in, list<uint> & link_stack, unsigned int version, unsigned int user_version ) {
	NI_NODE_READ
}

void NiNode::Write( ostream& out, map<NiObjectRef,uint> link_map, unsigned int version, unsigned int user_version ) const {
	NI_NODE_WRITE
}

string NiNode::asString( bool verbose ) const {
	NI_NODE_STRING
}

void NiNode::FixLinks( const vector<NiObjectRef> & objects, list<uint> & link_stack, unsigned int version, unsigned int user_version ) {
	NI_NODE_FIXLINKS
	//Connect children to their parents and remove any NULL ones
	for ( vector< NiAVObjectRef >::iterator it = children.begin(); it != children.end(); ) {
		if ( *it == NULL) {
			it = children.erase( it );
		} else {
			(*it)->SetParent(this);
			++it;
		}
	}
}

list<NiObjectRef> NiNode::GetRefs() const {
	NI_NODE_GETREFS
}

const Type & NiNode::GetType() const {
	return TYPE;
};

void NiNode::AddChild( Ref<NiAVObject> obj ) {
	if ( obj->GetParent() != NULL ) {
		throw runtime_error( "You have attempted to add a child to a NiNode which already is the child of another NiNode." );
	}
	obj->SetParent( this );
	children.push_back( obj );
}

void NiNode::RemoveChild( Ref<NiAVObject> obj ) {
	//Search child list for the one to remove
	for ( vector< NiAVObjectRef >::iterator it = children.begin(); it != children.end(); ) {
		if ( *it == obj ) {
			//Ensure that this child is not a skin influence
			NiNodeRef niNode = DynamicCast<NiNode>((*it));
			if ( niNode != NULL && niNode->IsSkinInfluence() == true ) {
				throw runtime_error("You cannot remove a node child that is a skin influence.  Detatch the skin first.");
			}
			(*it)->SetParent(NULL);
			it = children.erase( it );
		} else {
			++it;
		}
	}
}

void NiNode::ClearChildren() {
	for ( vector< NiAVObjectRef >::iterator it = children.begin(); it != children.end(); ++it) {
      if (*it) (*it)->SetParent(NULL);
	}
	children.clear();
}

vector< Ref<NiAVObject> > NiNode::GetChildren() const {
	return children;
}

void NiNode::AddEffect( Ref<NiDynamicEffect> obj ) {
   obj->SetParent( this );
   effects.push_back( obj );
}

void NiNode::RemoveEffect( Ref<NiDynamicEffect> obj ) {
   //Search Effect list for the one to remove
   for ( vector< NiDynamicEffectRef >::iterator it = effects.begin(); it != effects.end(); ) {
      if ( *it == obj ) {
         (*it)->SetParent(NULL);
         it = effects.erase( it );
      } else {
         ++it;
      }
   }
}

void NiNode::ClearEffects() {
   for ( vector< NiDynamicEffectRef >::iterator it = effects.begin(); it != effects.end(); ++it) {
      if (*it) (*it)->SetParent(NULL);
   }
   effects.clear();
}

vector< Ref<NiDynamicEffect> > NiNode::GetEffects() const {
   return effects;
}

bool NiNode::IsSkeletonRoot() const {
	return ( skins.size() > 0 );
}

bool NiNode::IsSkinInfluence() const {
	return ((flags & 8) == 0);
}

void NiNode::AddSkin( NiSkinInstance * skin_inst ) {
	skins.push_back( skin_inst );
}

void NiNode::RemoveSkin( NiSkinInstance * skin_inst ) {
	//Unflag any bones that were part of this skin instance
	vector<NiNodeRef> bones = skin_inst->GetBones();
	for ( uint i = 0; i < bones.size(); ++i ) {
		bones[i]->SetSkinFlag(false);
	}

	//Remove the reference
	skins.remove( skin_inst);

	//Ensure that any multiply referenced bone nodes still
	//have their skin flag set
	for ( list<NiSkinInstance*>::iterator it = skins.begin(); it != skins.end(); ++it ) {
		bones = (*it)->GetBones();
		for ( uint i = 0; i < bones.size(); ++i ) {
			bones[i]->SetSkinFlag(true);
		}
	}
}

void NiNode::SetSkinFlag( bool n ) {
	if ( IsSkinInfluence() == n ) {
		//Already set to the requested value
		return;
	} else {
		//Requested value is different, flip bit
		flags ^= 8;
	}
}

void NiNode::GoToSkeletonBindPosition() {
	//map<NiNodeRef, Matrix44> world_positions;

	//Loop through all attached skins, straightening the skeleton on each
	for ( list<NiSkinInstance*>::iterator it = skins.begin(); it != skins.end(); ++it ) {
		//Get Bone list and Skin Data
		vector<NiNodeRef> bone_nodes = (*it)->GetBones();
		NiSkinDataRef skin_data = (*it)->GetSkinData();

		if ( skin_data == NULL ) {
			//There's no skin data for this skin instance; skip it.
			continue;
		}

		//Make sure the counts match
		if ( bone_nodes.size() != skin_data->GetBoneCount() ) {
			throw runtime_error( "Bone counts in NiSkinInstance and attached NiSkinData must match" );
		}

		//Loop through all bones influencing this skin
		for ( uint i = 0; i < bone_nodes.size(); ++i ) {
			//Get current offset Matrix for this bone
			Matrix44 parent_offset = skin_data->GetBoneTransform(i);

			//Loop through all bones again, checking for any that have this bone as a parent
			for ( uint j = 0; j < bone_nodes.size(); ++j ) {
				if ( bone_nodes[j]->GetParent() == bone_nodes[i] ) {
					//cout << "Bone " << bones[j] << " has bone " << bones[i] << " as parent." << endl;
					//Node 2 has node 1 as a parent

					//Get child offset Matrix33
					Matrix44 child_offset = skin_data->GetBoneTransform(j);

					//Do calculation to get correct bone postion in relation to parent
					Matrix44 child_pos = child_offset.Inverse() * parent_offset;

					//bones[j]->SetWorldBindPos( child_pos );
					bone_nodes[j]->SetLocalRotation( child_pos.GetRotation() );
					bone_nodes[j]->SetLocalScale( 1.0f );
					bone_nodes[j]->SetLocalTranslation( child_pos.GetTranslation() );
				}
			}
		}
	}

	//Search for any NiTriBasedGeom classes lower in the scene graph and
	//reposition them
	RepositionGeom(this);
}

void NiNode::RepositionGeom( NiAVObjectRef root ) {
	//Check if this is a NiTriBasedGeom
	NiTriBasedGeomRef geom = DynamicCast<NiTriBasedGeom>(root);

	if ( geom != NULL ) {
		//This is a NiTriBasedGeom class
		//Get NiSkinInstance and NiSkinData

		NiSkinInstanceRef skin_inst = geom->GetSkinInstance();

		if ( skin_inst == NULL ) {
			return;
		}

		NiSkinDataRef skin_data = skin_inst->GetSkinData();

		if ( skin_data == NULL ) {
			return;
		}

		//Get bone nodes
		vector<NiNodeRef> bone_nodes = skin_inst->GetBones();

		//Make sure the counts match
		if ( bone_nodes.size() != skin_data->GetBoneCount() ) {
			throw runtime_error( "Bone counts in NiSkinInstance and attached NiSkinData must match" );
		}

		//There must be at least one bone to do anything
		if ( bone_nodes.size() == 0 ) {
			return;
		}

		//Use first bone (arbitrary choice)
		Matrix44 offset_mat = skin_data->GetBoneTransform(0);

		//Get built up rotations to the root of the skeleton from this bone
		Matrix44 bone_mat = bone_nodes[0]->GetWorldTransform();

		Matrix44 world_mat = offset_mat * bone_mat;

		Matrix44 result_mat = world_mat * geom->GetParent()->GetWorldTransform().Inverse();

		//--Set TriShape Local Position to Result--//
		geom->SetLocalRotation( result_mat.GetRotation() );
		geom->SetLocalTranslation( result_mat.GetTranslation() );
		geom->SetLocalScale( 1.0f );

		//TODO: Calculate the correct adjustment for the NiSkinData overall matrix
		//due to this change

		return;
	}

	//Check if this is a NiNode
	NiNodeRef node = DynamicCast<NiNode>(root);

	if ( node != NULL ) {
		//This is a NiNode, call this function on all children
		vector<NiAVObjectRef> children = node->GetChildren();
		for ( uint i = 0; i < children.size(); ++i ) {
			RepositionGeom( children[i] );
		}
	}
}<commit_msg>Removed code to re-position NiTriBasedGeom nodes as part of GoToSkeletonBindPosition since correct vertex positions can now be retrieved without doing this.<commit_after>/* Copyright (c) 2006, NIF File Format Library and Tools
All rights reserved.  Please see niflib.h for licence. */

#include "NiNode.h"
#include "NiAVObject.h"
#include "NiDynamicEffect.h"
#include "NiSkinInstance.h"
#include "NiSkinData.h"
#include "NiTriBasedGeom.h"
using namespace Niflib;

//Definition of TYPE constant
const Type NiNode::TYPE("NiNode", &NI_NODE_PARENT::TypeConst() );

NiNode::NiNode() NI_NODE_CONSTRUCT {}

NiNode::~NiNode() {
	//Clear Children
	ClearChildren();

	//Unbind any attached skins
	for ( list<NiSkinInstance*>::iterator it = skins.begin(); it != skins.end(); ++it ) {
		(*it)->SkeletonLost();
	}
}

void NiNode::Read( istream& in, list<uint> & link_stack, unsigned int version, unsigned int user_version ) {
	NI_NODE_READ
}

void NiNode::Write( ostream& out, map<NiObjectRef,uint> link_map, unsigned int version, unsigned int user_version ) const {
	NI_NODE_WRITE
}

string NiNode::asString( bool verbose ) const {
	NI_NODE_STRING
}

void NiNode::FixLinks( const vector<NiObjectRef> & objects, list<uint> & link_stack, unsigned int version, unsigned int user_version ) {
	NI_NODE_FIXLINKS
	//Connect children to their parents and remove any NULL ones
	for ( vector< NiAVObjectRef >::iterator it = children.begin(); it != children.end(); ) {
		if ( *it == NULL) {
			it = children.erase( it );
		} else {
			(*it)->SetParent(this);
			++it;
		}
	}
}

list<NiObjectRef> NiNode::GetRefs() const {
	NI_NODE_GETREFS
}

const Type & NiNode::GetType() const {
	return TYPE;
};

void NiNode::AddChild( Ref<NiAVObject> obj ) {
	if ( obj->GetParent() != NULL ) {
		throw runtime_error( "You have attempted to add a child to a NiNode which already is the child of another NiNode." );
	}
	obj->SetParent( this );
	children.push_back( obj );
}

void NiNode::RemoveChild( Ref<NiAVObject> obj ) {
	//Search child list for the one to remove
	for ( vector< NiAVObjectRef >::iterator it = children.begin(); it != children.end(); ) {
		if ( *it == obj ) {
			//Ensure that this child is not a skin influence
			NiNodeRef niNode = DynamicCast<NiNode>((*it));
			if ( niNode != NULL && niNode->IsSkinInfluence() == true ) {
				throw runtime_error("You cannot remove a node child that is a skin influence.  Detatch the skin first.");
			}
			(*it)->SetParent(NULL);
			it = children.erase( it );
		} else {
			++it;
		}
	}
}

void NiNode::ClearChildren() {
	for ( vector< NiAVObjectRef >::iterator it = children.begin(); it != children.end(); ++it) {
      if (*it) (*it)->SetParent(NULL);
	}
	children.clear();
}

vector< Ref<NiAVObject> > NiNode::GetChildren() const {
	return children;
}

void NiNode::AddEffect( Ref<NiDynamicEffect> obj ) {
   obj->SetParent( this );
   effects.push_back( obj );
}

void NiNode::RemoveEffect( Ref<NiDynamicEffect> obj ) {
   //Search Effect list for the one to remove
   for ( vector< NiDynamicEffectRef >::iterator it = effects.begin(); it != effects.end(); ) {
      if ( *it == obj ) {
         (*it)->SetParent(NULL);
         it = effects.erase( it );
      } else {
         ++it;
      }
   }
}

void NiNode::ClearEffects() {
   for ( vector< NiDynamicEffectRef >::iterator it = effects.begin(); it != effects.end(); ++it) {
      if (*it) (*it)->SetParent(NULL);
   }
   effects.clear();
}

vector< Ref<NiDynamicEffect> > NiNode::GetEffects() const {
   return effects;
}

bool NiNode::IsSkeletonRoot() const {
	return ( skins.size() > 0 );
}

bool NiNode::IsSkinInfluence() const {
	return ((flags & 8) == 0);
}

void NiNode::AddSkin( NiSkinInstance * skin_inst ) {
	skins.push_back( skin_inst );
}

void NiNode::RemoveSkin( NiSkinInstance * skin_inst ) {
	//Unflag any bones that were part of this skin instance
	vector<NiNodeRef> bones = skin_inst->GetBones();
	for ( uint i = 0; i < bones.size(); ++i ) {
		bones[i]->SetSkinFlag(false);
	}

	//Remove the reference
	skins.remove( skin_inst);

	//Ensure that any multiply referenced bone nodes still
	//have their skin flag set
	for ( list<NiSkinInstance*>::iterator it = skins.begin(); it != skins.end(); ++it ) {
		bones = (*it)->GetBones();
		for ( uint i = 0; i < bones.size(); ++i ) {
			bones[i]->SetSkinFlag(true);
		}
	}
}

void NiNode::SetSkinFlag( bool n ) {
	if ( IsSkinInfluence() == n ) {
		//Already set to the requested value
		return;
	} else {
		//Requested value is different, flip bit
		flags ^= 8;
	}
}

void NiNode::GoToSkeletonBindPosition() {
	//map<NiNodeRef, Matrix44> world_positions;

	//Loop through all attached skins, straightening the skeleton on each
	for ( list<NiSkinInstance*>::iterator it = skins.begin(); it != skins.end(); ++it ) {
		//Get Bone list and Skin Data
		vector<NiNodeRef> bone_nodes = (*it)->GetBones();
		NiSkinDataRef skin_data = (*it)->GetSkinData();

		if ( skin_data == NULL ) {
			//There's no skin data for this skin instance; skip it.
			continue;
		}

		//Make sure the counts match
		if ( bone_nodes.size() != skin_data->GetBoneCount() ) {
			throw runtime_error( "Bone counts in NiSkinInstance and attached NiSkinData must match" );
		}

		//Loop through all bones influencing this skin
		for ( uint i = 0; i < bone_nodes.size(); ++i ) {
			//Get current offset Matrix for this bone
			Matrix44 parent_offset = skin_data->GetBoneTransform(i);

			//Loop through all bones again, checking for any that have this bone as a parent
			for ( uint j = 0; j < bone_nodes.size(); ++j ) {
				if ( bone_nodes[j]->GetParent() == bone_nodes[i] ) {
					//cout << "Bone " << bones[j] << " has bone " << bones[i] << " as parent." << endl;
					//Node 2 has node 1 as a parent

					//Get child offset Matrix33
					Matrix44 child_offset = skin_data->GetBoneTransform(j);

					//Do calculation to get correct bone postion in relation to parent
					Matrix44 child_pos = child_offset.Inverse() * parent_offset;

					//bones[j]->SetWorldBindPos( child_pos );
					bone_nodes[j]->SetLocalRotation( child_pos.GetRotation() );
					bone_nodes[j]->SetLocalScale( 1.0f );
					bone_nodes[j]->SetLocalTranslation( child_pos.GetTranslation() );
				}
			}
		}
	}
}<|endoftext|>