#ifndef ___RB_GSL_HISTOGRAM3D_H___
#define ___RB_GSL_HISTOGRAM3D_H___

typedef struct {
  size_t nx, ny, nz;
  double * xrange;
  double * yrange;
  double * zrange;
  double * bin;
} mygsl_histogram3d;

typedef struct {
  gsl_histogram2d h;
} mygsl_histogram3d_view;


mygsl_histogram3d* mygsl_histogram3d_alloc(const size_t nx, const size_t ny,
                                           const size_t nz);
void mygsl_histogram3d_free (mygsl_histogram3d * h);
mygsl_histogram3d* mygsl_histogram3d_calloc_uniform(const size_t nx,
                                                    const size_t ny,
                                                    const size_t nz,
                                                    const double xmin,
                                                    const double xmax,
                                                    const double ymin,
                                                    const double ymax,
                                                    const double zmin,
                                                    const double zmax);
mygsl_histogram3d* mygsl_histogram3d_calloc(const size_t nx,
                                            const size_t ny,
                                            const size_t nz);
int mygsl_histogram3d_set_ranges_uniform (mygsl_histogram3d * h,
                                          double xmin, double xmax,
                                          double ymin, double ymax,
                                          double zmin, double zmax);
int mygsl_histogram3d_set_ranges (mygsl_histogram3d * h,
                                  const double xrange[], size_t xsize,
                                  const double yrange[], size_t ysize,
                                  const double zrange[], size_t zsize);
int mygsl_histogram3d_memcpy(mygsl_histogram3d * dest, const mygsl_histogram3d * src);
mygsl_histogram3d* mygsl_histogram3d_clone(const mygsl_histogram3d * src);
int mygsl_histogram3d_fread(FILE * stream, mygsl_histogram3d * h);
int mygsl_histogram3d_fwrite(FILE * stream, const mygsl_histogram3d * h);
int mygsl_histogram3d_increment(mygsl_histogram3d * h, double x, double y, double z);
int mygsl_histogram3d_accumulate (mygsl_histogram3d * h,
                                  double x, double y, double z, double weight);
int mygsl_histogram3d_increment2(mygsl_histogram3d * h,
                                 double x, double y, double z);
int mygsl_histogram3d_accumulate2(mygsl_histogram3d * h,
                                  double x, double y, double z, double weight);
double mygsl_histogram3d_get (const mygsl_histogram3d * h, const size_t i,
                              const size_t j, const size_t k);
int mygsl_histogram3d_get_xrange(const mygsl_histogram3d * h, const size_t i,
                                 double *xlower, double *xupper);
int mygsl_histogram3d_get_yrange(const mygsl_histogram3d * h, const size_t j,
                                 double *ylower, double *yupper);
int mygsl_histogram3d_get_zrange(const mygsl_histogram3d * h, const size_t k,
                                 double *zlower, double *zupper);
int mygsl_histogram3d_find (const mygsl_histogram3d * h,
                            const double x, const double y, const double z,
                            size_t * i, size_t * j, size_t *k);
gsl_histogram2d* mygsl_histogram3d_xyproject(const mygsl_histogram3d * h3,
                                             size_t kstart, size_t kend);
gsl_histogram2d* mygsl_histogram3d_xzproject(const mygsl_histogram3d * h3,
                                             size_t jstart, size_t jend);
gsl_histogram2d* mygsl_histogram3d_yzproject(const mygsl_histogram3d * h3,
                                             size_t istart, size_t iend);
int mygsl_histogram3d_scale(mygsl_histogram3d * h, double scale);
int mygsl_histogram3d_shift(mygsl_histogram3d * h, double shift);
double mygsl_histogram3d_xmax(const mygsl_histogram3d * h);
double mygsl_histogram3d_xmin(const mygsl_histogram3d * h);
double mygsl_histogram3d_ymax(const mygsl_histogram3d * h);
double mygsl_histogram3d_ymin(const mygsl_histogram3d * h);
double mygsl_histogram3d_zmax(const mygsl_histogram3d * h);
double mygsl_histogram3d_zmin(const mygsl_histogram3d * h);
double mygsl_histogram3d_max_val(const mygsl_histogram3d * h);
void mygsl_histogram3d_max_bin(const mygsl_histogram3d * h,
                               size_t *imax_out, size_t *jmax_out, size_t *kmax_out);
double mygsl_histogram3d_min_val(const mygsl_histogram3d * h);
void mygsl_histogram3d_min_bin(const mygsl_histogram3d * h,
                               size_t *imin_out, size_t *jmin_out, size_t *kmin_out);
double mygsl_histogram3d_sum (const mygsl_histogram3d * h);
double mygsl_histogram3d_xmean (const mygsl_histogram3d * h);
double mygsl_histogram3d_ymean (const mygsl_histogram3d * h);
double mygsl_histogram3d_zmean (const mygsl_histogram3d * h);
double mygsl_histogram3d_xsigma(const mygsl_histogram3d * h);
double mygsl_histogram3d_ysigma(const mygsl_histogram3d * h);
double mygsl_histogram3d_zsigma(const mygsl_histogram3d * h);
void mygsl_histogram3d_reset(mygsl_histogram3d * h);
int mygsl_histogram3d_equal_bins_p(const mygsl_histogram3d * h1,
                                   const mygsl_histogram3d * h2);
int mygsl_histogram3d_add(mygsl_histogram3d * h1, const mygsl_histogram3d * h2);
int mygsl_histogram3d_sub(mygsl_histogram3d * h1, const mygsl_histogram3d * h2);
int mygsl_histogram3d_mul(mygsl_histogram3d * h1, const mygsl_histogram3d * h2);
int mygsl_histogram3d_div(mygsl_histogram3d * h1, const mygsl_histogram3d * h2);

#endif
