#ifndef PROTO 
#define PROTO

#include "ptreelib.h"

static PyObject * Tree_InitDefaultParameters(Tree* self);
static PyObject * Tree_SetParameters(Tree* self, PyObject *args);

void domain_allocate(Tree *self);
void domain_deallocate(Tree *self);
void domain_Decomposition(Tree *self);
void domain_decompose(Tree *self);
int domain_findSplit(Tree *self, int cpustart, int ncpu, int first, int last);
void domain_shiftSplit(Tree *self);
void domain_findExchangeNumbers(Tree *self,int task, int partner, int sphflag, int *send, int *recv);
void domain_exchangeParticles(Tree *self,int partner, int sphflag, int send_count, int recv_count);
void domain_countToGo(Tree *self);
void domain_findExtent(Tree *self);
void domain_determineTopTree(Tree *self);
void domain_topsplit_local(Tree *self,int node, peanokey startkey);
void domain_topsplit(Tree *self,int node, peanokey startkey);
void domain_walktoptree(Tree *self,int no);
void domain_sumCost(Tree *self);
int domain_compare_toplist(const void *a, const void *b);
int domain_compare_key(const void *a, const void *b);
void do_box_wrapping(Tree *self);

void force_treeallocate(Tree *self,int maxnodes, int maxpart);
void force_treefree(Tree *self);
int force_treebuild(Tree *self,int npart);
int force_treebuild_single(Tree *self,int npart);
void force_create_empty_nodes(Tree *self,int no, int topnode, int bits, int x, int y, int z, int *nodecount,int *nextfree);
void force_insert_pseudo_particles(Tree *self);
void force_update_node_recursive(Tree *self,int no, int sib, int father);
void force_update_pseudoparticles(Tree *self);
void force_exchange_pseudodata(Tree *self);
void force_treeupdate_pseudos(Tree *self);
void force_flag_localnodes(Tree *self);
int force_treeevaluate(Tree *self,int target, int mode, double *ewaldcountsum);
int force_treeevaluate_sub(Tree *self,int target, int mode, double *ewaldcountsum);
void force_treeevaluate_potential(Tree *self,int target, int mode);
void force_treeevaluate_potential_sub(Tree *self,int target, int mode);
int force_treeevaluate_ewald_correction(Tree *self,int target, int mode, double pos_x, double pos_y, double pos_z,double aold);
int force_treeevaluate_ewald_correction_sub(Tree *self,int target, int mode, double pos_x, double pos_y, double pos_z,double aold);
double force_nearest(double x,double boxsize,double boxhalf);
void ewald_init(Tree *self);
double ewald_pot_corr(Tree *self,double dx, double dy, double dz);
double ewald_psi(double x[3]);
void ewald_force(int iii, int jjj, int kkk, double x[3], double force[3]);

void peano_hilbert_order(Tree *self);
int compare_key(const void *a, const void *b);
void reorder_gas(Tree *self);
void reorder_particles(Tree *self);
peanokey peano_hilbert_key(int x, int y, int z, int bits);


void ngb_treeallocate(Tree *self,int npart);
void ngb_treefree(Tree *self);
double ngb_periodic(double x,double boxsize,double boxhalf);
int ngb_treefind_variable(Tree *self,FLOAT searchcenter[3], FLOAT hsml, int *startnode);
int ngb_clear_buf(Tree *self,FLOAT searchcenter[3], FLOAT hsml, int numngb);


void gravity_tree(Tree *self);
void gravity_tree_sub(Tree *self);
void set_softenings(Tree *self);
int grav_tree_compare_key(const void *a, const void *b);


void density(Tree* self);
void density_evaluate(Tree* self,int target, int mode);
void density_sub(Tree* self);
void density_evaluate_sub(Tree* self,int target, int mode);
int dens_compare_key(const void *a, const void *b);
void density_init_hsml(Tree* self);

void sph_sub(Tree* self);
void sph_evaluate_sub(Tree* self,int target, int mode);

double dmax(double x, double y);
double dmin(double x, double y);
int imax(int x, int y);
int imin(int x, int y);

void compute_potential(Tree *self);
void compute_potential_sub(Tree *self);

size_t my_fwrite(Tree *self,void *ptr, size_t size, size_t nmemb, FILE * stream);
size_t my_fread(Tree *self,void *ptr, size_t size, size_t nmemb, FILE * stream);
#endif
