#ifdef _CVI_
 
#  include <ansi_c.h>
 
# else /* _CVI_ */
 
#  include <stdlib.h>
 
#  include <stdio.h>
 
#  include <string.h>
 
#endif /* _CVI_ */
 
 
 
#include "H2D.h"
 
 
 
#define H2DMAX 500
 
H2D *h2[H2DMAX];
 
//int Printf(char *format, ...);
 
 
 
int H2DClear(int h2d) {
 
  if (!h2[h2d]) return -1;
 
  memset(h2
[h2d
]->data
, 0,h2
[h2d
]->size 
);  
  h2[h2d]->min=0;
 
  h2[h2d]->max=0;
 
  h2[h2d]->nentries=0;
 
  return  0;
 
}
 
 
 
int H2DPrint(int h2d) {
 
  if (!h2[h2d]) return -1;
 
//Printf("PrintH2D nx=%d minx=%f stepx=%f ny=%d miny=%f stepy=%f size=%d\n", h2[h2d]->nx, h2[h2d]->minx, h2[h2d]->stepx, h2[h2d]->ny, h2[h2d]->miny, h2[h2d]->stepy, h2[h2d]->size ) ;
 
  return  0;
 
}
 
 
 
int H2DExist(int h) {
 
  if (h2[h]) return 1;
 
  else return 0;
 
}
 
 
 
int H2DGetBin(int h2d,int x, int y) {
 
  return x+h2[h2d]->nx * y;
 
}
 
 
 
int H2DCalculateBin(int h, int axis, double value) {
 
  int nx=0;
 
  double xmin=0,dx=0;
 
  int bin;
 
  switch (axis) {
 
    case 0:
 
      nx = H2DGetNbinsX(h);
 
      xmin= H2DGetMinX(h);
 
      dx = H2DGetStepX(h);
 
      break;
 
    case 1:
 
      nx = H2DGetNbinsY(h);
 
      xmin= H2DGetMinY(h);
 
      dx = H2DGetStepY(h);
 
      break;
 
    default:
 
      return -1;
 
  }
 
  if (dx<1e-10) return -1;
 
  if (value<xmin) return -1;
 
  bin = (int)((value-xmin)/dx);
 
  if (bin>=nx) return -1;
 
  else return bin;
 
}
 
 
 
int H2DFill(int h2d,double x, double y, double val) {
 
 
 
  int ix,iy;
 
  if (!h2[h2d]) return -1;
 
  ix = H2DCalculateBin(h2d,0,x);
 
  if (ix<0) return ix;
 
  iy = H2DCalculateBin(h2d,1,y);
 
  if (iy<0) return iy;
 
  return H2DFillBin(h2d,ix, iy, val);
 
}
 
 
 
int H2DFillBin(int h2d,int x, int y, double val) {
 
 
 
  int idx;
 
  if (!h2[h2d]) {
 
//Printf("FillH2D error h2d is not initialized\n");
 
    return -1;
 
  }
 
 
 
  idx = x+y*h2[h2d]->nx;
 
  h2[h2d]->data[idx]+=val;
 
//Printf("%d %d data %f %f\n",x,y,val, h2[h2d]->data[idx]);
 
  if (h2[h2d]->data[idx]>h2[h2d]->max) h2[h2d]->max= h2[h2d]->data[idx];
 
  if (h2[h2d]->data[idx]<h2[h2d]->min) h2[h2d]->min= h2[h2d]->data[idx];
 
  h2[h2d]->nentries++;
 
  return 0;
 
}
 
 
 
double H2DGetBinContent(int h2d,int atx,int aty) {
 
 
 
  int idx;
 
  if (!h2[h2d]) return 0;
 
  if (h2[h2d]->nx <= (unsigned int)atx)  return 0;
 
  if (h2[h2d]->ny <= (unsigned int)aty)  return 0;
 
  idx = atx+aty*h2[h2d]->nx;
 
  if (idx*sizeof(double) < h2[h2d]->size ) return h2[h2d]->data[idx];
 
  return 0;
 
}
 
 
 
int H2DInit(int h2d,const char *name,const char *title,int nx, double minx, double stepx, int ny, double miny, double stepy) {
 
 
 
  if (h2[h2d]) {
 
    h2[h2d] = NULL;
 
  }
 
  //printf("InitH2D hID=%d\n",h2d);
 
  h2
[h2d
] = (H2D 
*) malloc(sizeof(H2D
)); 
//h2  =h2d;
 
  H2DSetTitle(h2d,title);
 
  H2DSetName(h2d,name);
 
  h2[h2d]->id=H2D_ID;
 
  h2[h2d]->nx = nx;
 
  h2[h2d]->ny = ny;
 
  h2[h2d]->minx = minx;
 
  h2[h2d]->miny = miny;
 
  h2[h2d]->stepx = stepx;
 
  h2[h2d]->stepy = stepy;
 
  h2[h2d]->size = h2[h2d]->nx*h2[h2d]->ny*sizeof(double);
 
  h2
[h2d
]->data 
= (double *) malloc(h2
[h2d
]->size
); 
  h2[h2d]->len=sizeof(H2D)-sizeof(double *)+h2[h2d]->size;
 
  H2DClear(h2d);
 
  H2DPrint(h2d);
 
//Printf("InitH2D 0x%x\n", h2d );
 
  return  0;
 
}
 
 
 
double H2DGetXBinCenter(int h2d,int xbin) {
 
  return h2[h2d]->minx+xbin*h2[h2d]->stepx;
 
}
 
 
 
double H2DGetYBinCenter(int h2d,int ybin) {
 
  return h2[h2d]->miny+ybin*h2[h2d]->stepy;
 
}
 
 
 
int H2DWrite2File(int h2d,FILE *fp) {
 
 
 
  if (!fp) return -1;
 
//printf("H2D sizeof(H2D)=%lu len-datasize=%d len=%lu datasize=%d\t",sizeof(H2D)-sizeof(double *),h2[h2d]->len-h2[h2d]->size,h2[h2d]->len,h2[h2d]->size);
 
//printf("H2D sz=%d %d\n",sizeof(double),sizeof(double *));
 
  if (!H2DExist(h2d)){
 
    printf("Histogram H2D=%d is not initialized\n",h2d
);  
    return -1;
 
  }
 
  fwrite (h2
[h2d
], 1, sizeof(H2D
)-sizeof(double *), fp
);  
  fwrite (h2
[h2d
]->data
, 1, h2
[h2d
]->size
, fp
);  
  return  0;
 
}
 
 
 
int H2DWrite(int h2d,const char *fname,const char *opt) {
 
  FILE 
*fp
=fopen(fname
,opt
); 
  H2DWrite2File(h2d,fp);
 
  return  0;
 
}
 
 
 
int H2DSetTitle(int h2d,const char *title) {
 
  sprintf(h2
[h2d
]->title
,"%s",title
);  
  return 0;
 
}
 
 
 
int H2DSetTitleX(int h2d,const char *title) {
 
  sprintf(h2
[h2d
]->titlex
,"%s",title
);  
  return 0;
 
}
 
 
 
int H2DSetTitleY(int h2d,const char *title) {
 
  sprintf(h2
[h2d
]->titley
,"%s",title
);  
  return 0;
 
}
 
 
 
int H2DSetName(int h2d,const char *title) {
 
  return 0;
 
}
 
 
 
int H2DGetNbinsY(int h) {
 
  if (h2[h]) return h2[h]->ny;
 
  else return 0;
 
}
 
 
 
int H2DGetNbinsX(int h) {
 
  if (h2[h]) return h2[h]->nx;
 
  else return 0;
 
}
 
 
 
double H2DGetMinY(int h) {
 
  if (h2[h]) return h2[h]->miny;
 
  else return 0;
 
}
 
 
 
double H2DGetMinX(int h) {
 
  if (h2[h]) return h2[h]->minx;
 
  else return 0;
 
}
 
 
 
double H2DGetStepY(int h) {
 
  if (h2[h]) return h2[h]->stepy;
 
  else return 0;
 
}
 
 
 
double H2DGetStepX(int h) {
 
  if (h2[h]) return h2[h]->stepx;
 
  else return 0;
 
}
 
 
 
double H2DGetMin(int h) {
 
  if (h2[h]) return h2[h]->min;
 
  else return 0;
 
}
 
 
 
double H2DGetMax(int h) {
 
  if (h2[h]) return h2[h]->max;
 
  else return 0;
 
}
 
 
 
double * H2DGetData(int h) {
 
  if (h2[h]) return h2[h]->data;
 
  else return NULL;
 
}