#include<stdio.h>
#include<hdf5.h>
#include<HE5_HdfEosDef.h>
#include "ruby.h"
#include "narray.h"
#include<string.h>

/* for compatibility with ruby 1.6 */
#ifndef RSTRING_PTR
#define RSTRING_PTR(s) (RSTRING(s)->ptr)
#endif
#ifndef SafeStringValue
#define SafeStringValue(s) Check_SafeStr(s)
#endif

extern int   check_numbertype(char *);
extern int   change_numbertype(char *);
extern void  HE5Wrap_make_NArray1D_or_str(int, size_t, VALUE *, void **);
extern void  HE5Wrap_store_NArray1D_or_str(int, VALUE , void **);
extern void  change_chartype(hid_t, char *);

extern int     *hdfeos5_obj2cintary(VALUE);
extern long    *hdfeos5_obj2clongary(VALUE);
extern float   *hdfeos5_obj2cfloatary(VALUE);
extern signed long long   *hdfeos5_obj2csint64ary(VALUE);
extern unsigned long long *hdfeos5_obj2cunsint64ary(VALUE);

extern VALUE hdfeos5_ccharary2obj(char *, int, int);
extern VALUE hdfeos5_cintary2obj(int *, int, int, int *);
extern VALUE hdfeos5_clongary2obj(long *, int, int, int *);
extern VALUE hdfeos5_cunsint64ary2obj(unsigned long long *, int, int, int *);

extern void hdfeos5_freecintary(int *);
extern void hdfeos5_freeclongary(long *);
extern void hdfeos5_freecfloatary(float *);
extern void hdfeos5_freecsint64ary(signed long long *);
extern void hdfeos5_freecunsint64ary(unsigned long long *);

VALUE hdfeos5_ptwritelevel_char(VALUE, VALUE, VALUE);
VALUE hdfeos5_ptwritelevel_short(VALUE, VALUE, VALUE);
VALUE hdfeos5_ptwritelevel_int(VALUE, VALUE, VALUE);
VALUE hdfeos5_ptwritelevel_long(VALUE, VALUE, VALUE);
VALUE hdfeos5_ptwritelevel_float(VALUE, VALUE, VALUE);
VALUE hdfeos5_ptwritelevel_double(VALUE, VALUE, VALUE);

VALUE hdfeos5_ptreadlevel_char(VALUE);
VALUE hdfeos5_ptreadlevel_short(VALUE);
VALUE hdfeos5_ptreadlevel_int(VALUE);
VALUE hdfeos5_ptreadlevel_long(VALUE);
VALUE hdfeos5_ptreadlevel_float(VALUE);
VALUE hdfeos5_ptreadlevel_double(VALUE);

VALUE hdfeos5_ptupdatelevel_char(VALUE, VALUE, VALUE, VALUE);
VALUE hdfeos5_ptupdatelevel_short(VALUE, VALUE, VALUE, VALUE);
VALUE hdfeos5_ptupdatelevel_int(VALUE, VALUE, VALUE, VALUE);
VALUE hdfeos5_ptupdatelevel_long(VALUE, VALUE, VALUE, VALUE);
VALUE hdfeos5_ptupdatelevel_float(VALUE, VALUE, VALUE, VALUE);
VALUE hdfeos5_ptupdatelevel_double(VALUE, VALUE, VALUE, VALUE);

#define Cbyte_to_NArray(v, rank, shape, up) \
{ \
    struct NARRAY *ary; \
    v = na_make_object(NA_BYTE, rank, shape, cNArray); \
    GetNArray(v,ary); \
    up = (unsigned char *)ary->ptr; \
}
#define Cint_to_NArray(v, rank, shape, lp) \
{ \
    struct NARRAY *ary; \
    v = na_make_object(NA_SINT, rank, shape, cNArray); \
    GetNArray(v, ary); \
    lp = (short *)ary->ptr; \
}
#define Clint_to_NArray(v, rank, shape, lp) \
{ \
    struct NARRAY *ary; \
    v = na_make_object(NA_LINT, rank, shape, cNArray); \
    GetNArray(v, ary); \
    lp = (int *)ary->ptr; \
}
#define Clong_to_NArray(v, rank, shape, lp) \
{ \
    struct NARRAY *ary; \
    v = na_make_object(NA_LINT, rank, shape, cNArray); \
    GetNArray(v, ary); \
    lp = (long *)ary->ptr; \
}
#define Cfloat_to_NArray(v, rank, shape, fp) \
{ \
    struct NARRAY *ary; \
    v = na_make_object(NA_SFLOAT, rank, shape, cNArray); \
    GetNArray(v, ary); \
    fp = (float *)ary->ptr; \
}
#define Cdouble_to_NArray(v, rank, shape, dp); \
{ \
    struct NARRAY *ary; \
    v = na_make_object(NA_DFLOAT, rank, shape, cNArray); \
    GetNArray(v, ary); \
    dp = (double *)ary->ptr; \
}

/* Array or NArray to pointer and length (with no new allocation) */
#define Array_to_Cfloat_len_shape(obj, ptr, len, shape) \
{ \
    struct NARRAY *na; \
    obj = na_cast_object(obj, NA_SFLOAT); \
    GetNArray(obj, na); \
    ptr = (float *) NA_PTR(na,0); \
    len = na->total; \
    shape = na->shape; \
}
#define Array_to_Cdouble_len_shape(obj, ptr, len, shape) \
{ \
    struct NARRAY *na; \
    obj = na_cast_object(obj, NA_DFLOAT); \
    GetNArray(obj, na); \
    ptr = (double *) NA_PTR(na,0); \
    len = na->total; \
    shape = na->shape; \
}
#define Array_to_Cbyte_len_shape(obj, ptr, len, shape) \
{ \
    struct NARRAY *na; \
    obj = na_cast_object(obj, NA_BYTE); \
    GetNArray(obj, na); \
    ptr = (u_int8_t *) NA_PTR(na,0); \
    len = na->total; \
    shape = na->shape; \
}

#define Array_to_Cint_len_shape(obj, ptr, len, shape) \
{ \
    struct NARRAY *na; \
    obj = na_cast_object(obj, NA_SINT); \
    GetNArray(obj, na); \
    ptr = (int16_t *) NA_PTR(na,0); \
    len = na->total; \
    shape = na->shape; \
}
#define Array_to_Clint_len_shape(obj, ptr, len, shape) \
{ \
    struct NARRAY *na; \
    obj = na_cast_object(obj, NA_LINT); \
    GetNArray(obj, na); \
    ptr = (int32_t *) NA_PTR(na,0); \
    len = na->total; \
    shape = na->shape; \
}                              
#define Array_to_Clong_len_shape(obj, ptr, len, shape) \
{ \
    struct NARRAY *na; \
    obj = na_cast_object(obj, NA_LINT); \
    GetNArray(obj, na); \
    ptr = (long *) NA_PTR(na,0); \
    len = na->total; \
    shape = na->shape; \
}

#define maxcharsize  3000
#define HE5_NPOINT             64
#define HE5_NPOINTREGN        256
#define HE5_NRECS               1

static VALUE rb_eHE5Error;
static VALUE mNumRu = 0;
static VALUE cHE5;
static VALUE cHE5Pt;
static VALUE cHE5PtField;

struct HE5{                                         
  hid_t fid;
  char *name;
  int closed;
};

struct HE5Pt{
  hid_t ptid;
  char *name;   /* pointname */
  hid_t fid;
  VALUE file;
};

struct HE5PtField{
  char *name;  /* fieldname */
  char *levelname;
  int  fwdlink;
  int  bcklink;
  hid_t ptid;
  VALUE point;
};

static struct HE5Pt *
HE5Pt_init(hid_t ptid, char *name, hid_t fid, VALUE file)
{
  struct HE5Pt *HE5Point;
  HE5Point=xmalloc(sizeof(struct HE5Pt));
  HE5Point->ptid=ptid;
  HE5Point->fid=fid;
  HE5Point->name=xmalloc((strlen(name)+1)*sizeof(char));
  strcpy(HE5Point->name,name);
  HE5Point->file=file;
  return(HE5Point);
}

static struct HE5PtField *
HE5PtField_init(char *name, char *levelname, hid_t ptid, VALUE point)
{
  struct HE5PtField *HE5Ptlevel;
  HE5Ptlevel=xmalloc(sizeof(struct HE5PtField));
  HE5Ptlevel->ptid=ptid;
  HE5Ptlevel->point=point;
  HE5Ptlevel->name=xmalloc((strlen(name)+1)*sizeof(char));
  HE5Ptlevel->levelname=xmalloc((strlen(levelname)+1)*sizeof(char));
  strcpy(HE5Ptlevel->name,name);
  strcpy(HE5Ptlevel->levelname,levelname);
  return(HE5Ptlevel);
}

void
HE5Pt_free(struct HE5Pt *HE5_Point)
{
  free(HE5_Point->name);
  free(HE5_Point);
}

void
HE5PtField_free(struct HE5PtField *HE5Pt_level)
{
  free(HE5Pt_level->name);
  free(HE5Pt_level->levelname);
  free(HE5Pt_level);
}

static void
he5ptfield_mark_obj(struct HE5PtField *he5fld)
{
    VALUE ptr;

    ptr = he5fld->point;
    rb_gc_mark(ptr);
}

static void
he5pt_mark_obj(struct HE5Pt *he5pt)
{
    VALUE ptr;

    ptr = he5pt->file;
    rb_gc_mark(ptr);
}

static long
search_levelsize(hid_t i_ptid, char *i_fieldname)
{
    int i_level=0,i,j;
    int i_nlevels;
    long o_strbufsize=FAIL;
    herr_t status;

    HE5_CmpDTSinfo dtsinfo;

    i_nlevels = HE5_PTnlevels(i_ptid);
    if(i_nlevels < 0 ) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    for(i=0;i<i_nlevels;i++) {
       status = HE5_PTlevelinfo(i_ptid, i, &dtsinfo); 
       if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
       for(j=0;j<dtsinfo.nfields;j++) {
          if(strcmp(i_fieldname,dtsinfo.fieldname[j])==0){
             i_level = i;
          }
       }
    }
    status = HE5_PTgetlevelname(i_ptid, i_level, NULL, &o_strbufsize);
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    return o_strbufsize;
}

static char*
search_levelname(hid_t i_ptid, char *i_fieldname)
{
    int i_level=0,i,j;
    int i_nlevels;
    char *o_levelname;
    long o_strbufsize=FAIL;
    herr_t status;

    HE5_CmpDTSinfo dtsinfo;

    i_nlevels = HE5_PTnlevels(i_ptid);
    if(i_nlevels < 0 ) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    for(i=0;i<i_nlevels;i++) {
       status = HE5_PTlevelinfo(i_ptid, i, &dtsinfo); 
       if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
       for(j=0;j<dtsinfo.nfields;j++) {
          if(strcmp(i_fieldname,dtsinfo.fieldname[j])==0){
             i_level=i;
          }
       }
    }

    status = HE5_PTgetlevelname(i_ptid, i_level, NULL, &o_strbufsize);
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    o_levelname = ALLOCA_N(char,(o_strbufsize+1)*sizeof(char));

    status = HE5_PTgetlevelname(i_ptid, i_level, o_levelname, &o_strbufsize);
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    return o_levelname;
}

static void *
sort_data_byte(hid_t i_ptid, int i_level, char* o_linkfield,const int* shape)
{
    int  i,j;
    int  shape_parent, shape_child;    /* NArray uses int instead of size_t */
    char *o_data_parent;
    char *o_data_child;
    herr_t status;

    shape_parent=HE5_PTnrecs(i_ptid, i_level);
    o_data_parent=ALLOCA_N(char,shape_parent);

    shape_child=HE5_PTnrecs(i_ptid, i_level+1);
    o_data_child=ALLOCA_N(char,shape_child);

   // parent 
    status = HE5_PTreadlevelF(i_ptid, i_level, o_linkfield, H5T_NATIVE_CHAR, o_data_parent);
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
   // child 
    status = HE5_PTreadlevelF(i_ptid, i_level+1, o_linkfield, H5T_NATIVE_CHAR, o_data_child);
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    for(i=0;i<shape_child;i++){
       for(j=0;j<shape_parent;++j){
          if( *(char *)&o_data_child[i] == *(char *)&o_data_parent[j]){
             *(int *)&shape[i] = j;
          }
       }
    }
    return 0;
}

static void *
sort_data_short(hid_t i_ptid, int i_level, char* o_linkfield,const int* shape)
{
    int  i,j;
    int  shape_parent, shape_child;    /* NArray uses int instead of size_t */
    short *o_data_parent;
    short *o_data_child;
    herr_t status;

    shape_parent=HE5_PTnrecs(i_ptid, i_level);
    o_data_parent=ALLOCA_N(short,shape_parent);

    shape_child=HE5_PTnrecs(i_ptid, i_level+1);
    o_data_child=ALLOCA_N(short,shape_child);

   // parent 
    status = HE5_PTreadlevelF(i_ptid, i_level, o_linkfield, H5T_NATIVE_SHORT, o_data_parent);
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
   // child 
    status = HE5_PTreadlevelF(i_ptid, i_level+1, o_linkfield, H5T_NATIVE_SHORT, o_data_child);
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    for(i=0;i<shape_child;i++){
       for(j=0;j<shape_parent;++j){
          if( *(short *)&o_data_child[i] == *(short *)&o_data_parent[j]){
             *(int *)&shape[i] = j;
          }
       }
    }
    return 0;
}

static void *
sort_data_int(hid_t i_ptid, int i_level, char* o_linkfield,const int* shape)
{
    int  i,j;
    int  shape_parent, shape_child;    /* NArray uses int instead of size_t */
    int  *o_data_parent;
    int  *o_data_child;
    herr_t status;

    shape_parent=HE5_PTnrecs(i_ptid, i_level);
    o_data_parent=ALLOCA_N(int,shape_parent);

    shape_child=HE5_PTnrecs(i_ptid, i_level+1);
    o_data_child=ALLOCA_N(int,shape_child);

   // parent 
    status = HE5_PTreadlevelF(i_ptid, i_level, o_linkfield, HE5T_NATIVE_INT, o_data_parent);
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
   // child 
    status = HE5_PTreadlevelF(i_ptid, i_level+1, o_linkfield, HE5T_NATIVE_INT, o_data_child);
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    for(i=0;i<shape_child;i++){
       for(j=0;j<shape_parent;++j){
          if( *(int *)&o_data_child[i] == *(int *)&o_data_parent[j]){
             *(int *)&shape[i] = j;
          }
       }
    }
    return 0;
}

static void *
sort_data_long(hid_t i_ptid, int i_level, char* o_linkfield,const int* shape)
{
    int  i,j;
    int  shape_parent, shape_child;    /* NArray uses int instead of size_t */
    long *o_data_parent;
    long *o_data_child;
    herr_t status;

    shape_parent=HE5_PTnrecs(i_ptid, i_level);
    o_data_parent=ALLOCA_N(long,shape_parent);

    shape_child=HE5_PTnrecs(i_ptid, i_level+1);
    o_data_child=ALLOCA_N(long,shape_child);

   // parent 
    status = HE5_PTreadlevelF(i_ptid, i_level, o_linkfield, H5T_NATIVE_LONG, o_data_parent);
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
   // child 
    status = HE5_PTreadlevelF(i_ptid, i_level+1, o_linkfield, H5T_NATIVE_LONG, o_data_child);
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    for(i=0;i<shape_child;i++){
       for(j=0;j<shape_parent;++j){
          if( *(long *)&o_data_child[i] == *(long *)&o_data_parent[j]){
             *(int *)&shape[i] = j;
          }
       }
    }
    return 0;
}

static void *
sort_data_float(hid_t i_ptid, int i_level, char* o_linkfield,const int* shape)
{
    int  i,j;
    int  shape_parent, shape_child;    /* NArray uses int instead of size_t */
    float *o_data_parent;
    float *o_data_child;
    herr_t status;

    shape_parent=HE5_PTnrecs(i_ptid, i_level);
    o_data_parent=ALLOCA_N(float,shape_parent);

    shape_child=HE5_PTnrecs(i_ptid, i_level+1);
    o_data_child=ALLOCA_N(float,shape_child);

   // parent 
    status = HE5_PTreadlevelF(i_ptid, i_level, o_linkfield, H5T_NATIVE_FLOAT, o_data_parent);
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
   // child 
    status = HE5_PTreadlevelF(i_ptid, i_level+1, o_linkfield, H5T_NATIVE_FLOAT, o_data_child);
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    for(i=0;i<shape_child;i++){
       for(j=0;j<shape_parent;++j){
          if( *(float *)&o_data_child[i] == *(float *)&o_data_parent[j]){
             *(int *)&shape[i] = j;
          }
       }
    }
    return 0;
}

static void *
sort_data_double(hid_t i_ptid, int i_level, char* o_linkfield,const int* shape)
{
    int  i,j;
    int  shape_parent, shape_child;    /* NArray uses int instead of size_t */
    double *o_data_parent;
    double *o_data_child;
    herr_t status;

    shape_parent=HE5_PTnrecs(i_ptid, i_level);
    o_data_parent=ALLOCA_N(double,shape_parent);

    shape_child=HE5_PTnrecs(i_ptid, i_level+1);
    o_data_child=ALLOCA_N(double,shape_child);

   // parent 
    status = HE5_PTreadlevelF(i_ptid, i_level, o_linkfield, H5T_NATIVE_DOUBLE, o_data_parent);
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
   // child 
    status = HE5_PTreadlevelF(i_ptid, i_level+1, o_linkfield, H5T_NATIVE_DOUBLE, o_data_child);
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    for(i=0;i<shape_child;i++){
       for(j=0;j<shape_parent;++j){
          if( *(double *)&o_data_child[i] == *(double *)&o_data_parent[j]){
             *(int *)&shape[i] = j;
          }
       }
    }
    return 0;
}

VALUE
HE5Pt_clone(VALUE point)
{
    VALUE clone;
    struct HE5Pt *he5pt1, *he5pt2;

    Data_Get_Struct(point, struct HE5Pt, he5pt1);
    he5pt2 = HE5Pt_init(he5pt1->ptid, he5pt1->name, he5pt1->fid, he5pt1->file);
    clone = Data_Wrap_Struct(cHE5Pt, he5pt_mark_obj, HE5Pt_free, he5pt2);
    CLONESETUP(clone, point);
    return clone;
}

VALUE
HE5PtField_clone(VALUE level)
{
    VALUE clone;
    struct HE5PtField *he5fld1, *he5fld2;

    Data_Get_Struct(level, struct HE5PtField, he5fld1);
    he5fld2 = HE5PtField_init(he5fld1->name, he5fld1->levelname, he5fld1->ptid, he5fld1->point);
    clone = Data_Wrap_Struct(cHE5PtField, he5ptfield_mark_obj, HE5PtField_free, he5fld2);
    CLONESETUP(clone, level);
    return clone;
}

VALUE
hdfeos5_ptcreate(VALUE mod, VALUE pointname)
{
    hid_t i_fid;
    hid_t ptid;
    char* i_pointname;
    struct HE5 *he5file;
    struct HE5Pt *he5point;
    char*  file;
    VALUE Point;

    rb_secure(4);
    Data_Get_Struct(mod, struct HE5, he5file);
    i_fid=he5file->fid;
    file=he5file->name;

    Check_Type(pointname,T_STRING);
    SafeStringValue(pointname);
    i_pointname = RSTRING_PTR(pointname);

    ptid = HE5_PTcreate(i_fid, i_pointname);
    if(ptid == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    he5point = HE5Pt_init(ptid, i_pointname, i_fid, mod);
    Point = Data_Wrap_Struct(cHE5Pt, he5pt_mark_obj, HE5Pt_free, he5point);
    return(Point);
}

VALUE
hdfeos5_ptattach(VALUE mod, VALUE pointname)
{
    hid_t i_fid;
    hid_t ptid;
    char *i_pointname, *i_fname;
    struct HE5 *he5file;
    struct HE5Pt *he5point;
    VALUE Point;

    rb_secure(4);
    Data_Get_Struct(mod, struct HE5, he5file);
    i_fid=he5file->fid;
    i_fname=he5file->name;

    Check_Type(pointname,T_STRING);
    SafeStringValue(pointname);
    i_pointname = RSTRING_PTR(pointname);

    ptid = HE5_PTattach(i_fid, i_pointname);
    if(ptid == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    he5point = HE5Pt_init(ptid, i_pointname, i_fid, mod);
    Point = Data_Wrap_Struct(cHE5Pt, he5pt_mark_obj, HE5Pt_free, he5point);
    return(Point);
}

VALUE
hdfeos5_ptdetach(VALUE mod)
{
    hid_t i_ptid;
    herr_t o_rtn_val;
    VALUE rtn_val;

    struct HE5Pt *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Pt, he5point);
    i_ptid=he5point->ptid;

    o_rtn_val = HE5_PTdetach(i_ptid);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;
    return(rtn_val);
}

VALUE
hdfeos5_ptnrecs(VALUE mod, VALUE level)
{
    hid_t i_ptid;
    int i_level;
    hsize_t o_nrec;
    VALUE nrec;
    struct HE5Pt *he5point;

    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Pt, he5point);
    i_ptid=he5point->ptid;
    Check_Type(level,T_FIXNUM);
    i_level = NUM2LONG(level);
    o_nrec = HE5_PTnrecs(i_ptid, i_level);
    if(o_nrec < 0) rb_raise(rb_eHE5Error, "ERROR [%s:%d],__FILE__,__LINE__");
    nrec = INT2NUM(o_nrec);
    return(nrec);
}

VALUE
hdfeos5_ptnlevels(VALUE mod)
{
    hid_t i_ptid;
    int o_nlevels;
    VALUE nlevels;
    struct HE5Pt *he5point;

    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Pt, he5point);
    i_ptid=he5point->ptid;

    o_nlevels = HE5_PTnlevels(i_ptid);
    if(o_nlevels < 0 ) rb_raise(rb_eHE5Error, "ERROR [%s:%d],__FILE__,__LINE__");
    nlevels = LONG2NUM(o_nlevels);
    return(nlevels);
}

VALUE
hdfeos5_ptnfields(VALUE mod)
{
    int i;
    hid_t i_ptid;
    int o_nflds=0;
    int o_nflds1=0;
    int o_nlevels;
    char *o_fieldlist;
    char *o_fieldlist1;
    long o_strbufsize=FAIL;
    long o_strbufsize1=FAIL;
    VALUE fieldlist;
    VALUE nflds;
    struct HE5Pt *he5point;

    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Pt, he5point);
    i_ptid=he5point->ptid;

    o_nlevels = HE5_PTnlevels(i_ptid);
    if(o_nlevels < 0 ) rb_raise(rb_eHE5Error, "ERROR [%s:%d],__FILE__,__LINE__");
    for(i=0;i<o_nlevels;i++) {
      o_nflds1 = HE5_PTnfields(i_ptid, i, NULL, &o_strbufsize1);
      if(o_nflds1 < 0 ) rb_raise(rb_eHE5Error, "ERROR [%s:%d],__FILE__,__LINE__");
      o_strbufsize += o_strbufsize1+1;
    }
    o_fieldlist = ALLOCA_N(char,(o_strbufsize)*sizeof(char));
    strcpy(o_fieldlist,"");

    for(i=0;i<o_nlevels;i++) {
      o_nflds1 = HE5_PTnfields(i_ptid, i, NULL, &o_strbufsize1);
      if(o_nflds1 < 0 ) rb_raise(rb_eHE5Error, "ERROR [%s:%d],__FILE__,__LINE__");
      o_fieldlist1 = ALLOC_N(char,(o_strbufsize1+1)*sizeof(char));

      o_nflds1 = HE5_PTnfields(i_ptid, i, o_fieldlist1, &o_strbufsize1);
      if(o_nflds1 < 0 ) rb_raise(rb_eHE5Error, "ERROR [%s:%d],__FILE__,__LINE__");
      strcat(o_fieldlist, o_fieldlist1);
      if(o_nlevels > i+1) strncat(o_fieldlist,",",1);
      free(o_fieldlist1);
      o_nflds += o_nflds1;
    }
    fieldlist = rb_str_new(o_fieldlist,o_strbufsize);
    nflds = INT2NUM(o_nflds);
    return rb_ary_new3(2, nflds, fieldlist);
}

VALUE
hdfeos5_ptgetlevelname(VALUE mod)
{
    int i;
    hid_t i_ptid;
    int o_nlevels;
    char *o_levelname;
    char *o_levelname1;
    long o_strbufsize=FAIL;
    long o_strbufsize1=FAIL;
    herr_t o_rtn_val;
    VALUE nlevels;
    VALUE levelname;
    struct HE5Pt *he5point;

    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Pt, he5point);
    i_ptid=he5point->ptid;

    o_nlevels = HE5_PTnlevels(i_ptid);
    if(o_nlevels < 0 ) rb_raise(rb_eHE5Error, "ERROR [%s:%d],__FILE__,__LINE__");
    for(i=0;i<o_nlevels;i++) {
      o_rtn_val = HE5_PTgetlevelname(i_ptid, i, NULL, &o_strbufsize1);
      if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d],__FILE__,__LINE__");
      o_strbufsize += o_strbufsize1+1;
    }
    o_levelname = ALLOCA_N(char,(o_strbufsize)*sizeof(char));
    strcpy(o_levelname,"");

    for(i=0;i<o_nlevels;i++) {
      o_rtn_val = HE5_PTgetlevelname(i_ptid, i, NULL, &o_strbufsize1);
      if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d],__FILE__,__LINE__");
      o_levelname1 = ALLOC_N(char,(o_strbufsize1+1)*sizeof(char));

      o_rtn_val = HE5_PTgetlevelname(i_ptid, i, o_levelname1, &o_strbufsize1);
      if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d],__FILE__,__LINE__");
      strcat(o_levelname, o_levelname1);
      if(o_nlevels > i+1) strncat(o_levelname,",",1);
      free(o_levelname1);
    }
    levelname = rb_str_new(o_levelname,o_strbufsize);
    nlevels = INT2NUM(o_nlevels);
    return rb_ary_new3(2, nlevels, levelname);

}

VALUE
hdfeos5_ptdeflevel(VALUE file, VALUE levelname, VALUE nfields, VALUE rank, VALUE fieldlist, VALUE dimlist, VALUE datatype)
{
    int i,nn;
    hid_t i_ptid;
    char *i_levelname;
    int  i_nfields;
    int  *i_rank;
    char *i_fieldlist;
    long *i_dimlist;
    char *i_datatype;
    int *i_ntypelist; 
    char i_dtypecheck[HE5_HDFE_UTLBUFSIZE];
    int *i_array;
    int o_rtn_val;
    VALUE rtn_val;

    size_t slen[maxcharsize];
    char   *pntr[maxcharsize];

    rb_secure(4);
    struct HE5Pt *he5point;
    Data_Get_Struct(file, struct HE5Pt, he5point);
    i_ptid=he5point->ptid;

    i_nfields=NUM2INT(nfields);
    Check_Type(levelname,T_STRING);
    SafeStringValue(levelname);
    i_levelname = RSTRING_PTR(levelname);

    i_rank=ALLOCA_N(int,i_nfields*sizeof(int));
    rank = rb_Array(rank);
    i_rank = hdfeos5_obj2cintary(rank);

    Check_Type(fieldlist,T_STRING);
    SafeStringValue(fieldlist);
    i_fieldlist = RSTRING_PTR(fieldlist);

    dimlist = rb_Array(dimlist);
    i_dimlist = hdfeos5_obj2clongary(dimlist);

    Check_Type(datatype,T_STRING);
    SafeStringValue(datatype);
    i_datatype = RSTRING_PTR(datatype);
    nn = HE5_EHparsestr(i_datatype, ',', pntr, slen);
    i_array = ALLOCA_N(int, i_nfields);
    i_ntypelist = ALLOCA_N(int, i_nfields);
    for(i=0;i<i_nfields;i++) {
      if(i_rank[i] == 1){
        i_array[i]=TRUE;
      } else {
        i_array[i]=FALSE;
      }
      memmove(i_dtypecheck, pntr[i], slen[i]);
      i_dtypecheck[slen[i]] = 0;
      i_ntypelist[i] = check_numbertype(i_dtypecheck);
    }
    o_rtn_val = HE5_PTdeflevelF(i_ptid, i_levelname, i_rank, i_fieldlist, i_dimlist, i_ntypelist, i_array);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;
    hdfeos5_freecintary(i_rank);
    hdfeos5_freeclongary(i_dimlist);
    return Qtrue;
}

VALUE
hdfeos5_ptdeflinkage(VALUE file, VALUE parent_level, VALUE child_level,VALUE linklevel)
{
    hid_t i_ptid;
    char *i_parent_level;
    char *i_child_level;
    char *i_linklevel;
    herr_t o_rtn_val;
    VALUE rtn_val;

    rb_secure(4);
    struct HE5Pt *he5point;
    Data_Get_Struct(file, struct HE5Pt, he5point);
    i_ptid=he5point->ptid;

    Check_Type(parent_level,T_STRING);
    SafeStringValue(parent_level);
    i_parent_level = RSTRING_PTR(parent_level);
    Check_Type(child_level,T_STRING);
    SafeStringValue(child_level);
    i_child_level = RSTRING_PTR(child_level);
    Check_Type(linklevel,T_STRING);
    SafeStringValue(linklevel);
    i_linklevel = RSTRING_PTR(linklevel);

    o_rtn_val = HE5_PTdeflinkage(i_ptid, i_parent_level, i_child_level, i_linklevel);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;
    return(rtn_val);
}

VALUE
hdfeos5_ptwritelevel(VALUE mod, VALUE count, VALUE data, VALUE ntype)
{
    char *chk_ntype;
    Check_Type(ntype,T_STRING);
    SafeStringValue(ntype);
    chk_ntype = RSTRING_PTR(ntype);

    switch (check_numbertype(chk_ntype)){
    case  HE5T_NATIVE_CHAR:
    case  HE5T_NATIVE_SCHAR:
    case  HE5T_NATIVE_UCHAR:
    case  HE5T_CHARSTRING:
        return hdfeos5_ptwritelevel_char(mod,  count,  data);
	break;

    case  HE5T_NATIVE_INT8:
    case  HE5T_NATIVE_UINT8:
        return hdfeos5_ptwritelevel_char(mod,  count,  data);
	break;

    case  HE5T_NATIVE_SHORT:
    case  HE5T_NATIVE_USHORT:
    case  HE5T_NATIVE_INT16:
    case  HE5T_NATIVE_UINT16:
        return hdfeos5_ptwritelevel_short(mod,  count,  data);
	break;

    case  HE5T_NATIVE_INT:
    case  HE5T_NATIVE_UINT:
    case  HE5T_NATIVE_INT32:
    case  HE5T_NATIVE_UINT32:
        return hdfeos5_ptwritelevel_int(mod,  count,  data);
	break;

    case  HE5T_NATIVE_LONG:
        return hdfeos5_ptwritelevel_long(mod,  count,  data);
	break;

    case  HE5T_NATIVE_FLOAT:
        return hdfeos5_ptwritelevel_float(mod,  count,  data);
	break;

    case  HE5T_NATIVE_DOUBLE:
        return hdfeos5_ptwritelevel_double(mod,  count,  data);
	break;
    default:
	rb_raise(rb_eHE5Error, "not match data type [%s:%d]",__FILE__,__LINE__);
    }
}

VALUE
hdfeos5_ptwriteattr(VALUE mod, VALUE attrname, VALUE numbertype, VALUE count, VALUE datbuf)
{
    hid_t i_ptid;
    char *i_attrname;
    hid_t i_numbertype;
    int i_numbertypechk;
    unsigned long long *i_count;
    void *i_datbuf;
    herr_t o_rtn_val;
    VALUE rtn_val;

    struct HE5Pt *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Pt, he5point);
    i_ptid=he5point->ptid;

    Check_Type(attrname,T_STRING);
    SafeStringValue(attrname);
    Check_Type(numbertype,T_STRING);
    SafeStringValue(numbertype);
    count = rb_Array(count);

    i_attrname = RSTRING_PTR(attrname);
    i_numbertype    = change_numbertype(RSTRING_PTR(numbertype));
    i_numbertypechk = check_numbertype(RSTRING_PTR(numbertype));
    i_count = hdfeos5_obj2cunsint64ary(count);

    HE5Wrap_store_NArray1D_or_str(i_numbertypechk, datbuf, &i_datbuf); 
    o_rtn_val = HE5_PTwriteattr(i_ptid, i_attrname, i_numbertype, i_count, i_datbuf);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;
    hdfeos5_freecunsint64ary(i_count);
    return(rtn_val);
}

VALUE
hdfeos5_pt_get_att(VALUE mod, VALUE attrname)
{
    VALUE result;
    hid_t i_ptid;
    char *i_attrname;
    hid_t o_ntype;
    void *o_datbuf;
    unsigned long long o_count;
    herr_t o_rtn_val;

    struct HE5Pt *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Pt, he5point);
    i_ptid=he5point->ptid;

    Check_Type(attrname,T_STRING);
    SafeStringValue(attrname);
    i_attrname = RSTRING_PTR(attrname);

    o_rtn_val = HE5_PTattrinfo(i_ptid, i_attrname, &o_ntype, &o_count);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    HE5Wrap_make_NArray1D_or_str(o_ntype, o_count, &result, &o_datbuf); 
    o_rtn_val = HE5_PTreadattr(i_ptid, i_attrname, o_datbuf);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    return result;
}

VALUE
hdfeos5_ptfieldinfo(VALUE mod)
{
    int i,j;
    hid_t i_ptid;
    int i_level;
    int i_nrecs;
    int i_rank=1;
    int i_fldnum=0;
    char *i_levelname;
    char *i_fieldname;
    char o_ntype[HE5_BLKSIZE];
    int  o_dims[HE5_BLKSIZE];

    HE5_CmpDTSinfo    dtsinfo;

    herr_t o_rtn_val;
    VALUE rank;
    VALUE dims;
    VALUE ntype;
    VALUE fieldname;

    struct HE5PtField *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5PtField, he5point);
    i_levelname=he5point->levelname;
    i_fieldname=he5point->name;
    i_ptid=he5point->ptid;
    
    i_level=HE5_PTlevelindx(i_ptid, i_levelname);
    if(i_level <0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    i_nrecs=HE5_PTnrecs(i_ptid, i_level);
    o_dims[0]=i_nrecs;

    o_rtn_val = HE5_PTlevelinfo(i_ptid, i_level, &dtsinfo); 
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    for(i=0;i<dtsinfo.nfields;i++) {
       if(strcmp(i_fieldname,dtsinfo.fieldname[i])==0) {
          i_fldnum=i;
          for(j=0;j<dtsinfo.rank[i_fldnum];j++) {
             if( dtsinfo.rank[i_fldnum] > 1 || dtsinfo.dims[i_fldnum][j] > 1) {
               o_dims[j+1] = dtsinfo.dims[i_fldnum][j];
               i_rank += 1;
             }
          }
          break;
       }
    }
    rank = INT2NUM(i_rank);
    dims = hdfeos5_cintary2obj((int *)o_dims, i_rank, 1, &i_rank);
    change_chartype(dtsinfo.numtype[i_fldnum],o_ntype);
    ntype =rb_str_new(o_ntype,strlen(o_ntype));
    fieldname=rb_str_new2(i_fieldname);
    return rb_ary_new3(4, rank, dims, ntype, fieldname);
}

VALUE
hdfeos5_ptreadlevel(VALUE mod, VALUE ntype)
{
    char *chk_ntype;
    Check_Type(ntype,T_STRING);
    SafeStringValue(ntype);
    chk_ntype = RSTRING_PTR(ntype);

    switch (check_numbertype(chk_ntype)){
    case  HE5T_NATIVE_CHAR:
    case  HE5T_NATIVE_SCHAR:
    case  HE5T_NATIVE_UCHAR:
    case  HE5T_CHARSTRING:
        return hdfeos5_ptreadlevel_char(mod);
	break;

    case  HE5T_NATIVE_INT8:
    case  HE5T_NATIVE_UINT8:
        return hdfeos5_ptreadlevel_char(mod);
	break;

    case  HE5T_NATIVE_SHORT:
    case  HE5T_NATIVE_USHORT:
    case  HE5T_NATIVE_INT16:
    case  HE5T_NATIVE_UINT16:
        return hdfeos5_ptreadlevel_short(mod);
	break;

    case  HE5T_NATIVE_INT:
    case  HE5T_NATIVE_UINT:
    case  HE5T_NATIVE_INT32:
    case  HE5T_NATIVE_UINT32:
        return hdfeos5_ptreadlevel_int(mod);
	break;

    case  HE5T_NATIVE_LONG:
        return hdfeos5_ptreadlevel_long(mod);
	break;

    case  HE5T_NATIVE_FLOAT:
        return hdfeos5_ptreadlevel_float(mod);
	break;

    case  HE5T_NATIVE_DOUBLE:
        return hdfeos5_ptreadlevel_double(mod);
	break;
    default:
	rb_raise(rb_eHE5Error, "not match data type [%s:%d]",__FILE__,__LINE__);
    }
}

VALUE
hdfeos5_ptinqdatatype(VALUE mod, VALUE levelname, VALUE attrname, VALUE group)
{
    hid_t i_ptid;
    char *i_levelname;
    char *i_attrname;
    int i_group;
    hid_t i_datatype = FAIL;
    H5T_class_t o_classid;
    H5T_order_t o_order;
    size_t o_size;
    herr_t o_rtn_val;
    VALUE classid;
    VALUE order;
    VALUE size;

    struct HE5Pt *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Pt, he5point);
    i_ptid=he5point->ptid;

    Check_Type(levelname,T_STRING);
    SafeStringValue(levelname);
    Check_Type(attrname,T_STRING);
    SafeStringValue(attrname);

    i_levelname = RSTRING_PTR(levelname);
    i_attrname = RSTRING_PTR(attrname);
    i_group = NUM2INT(group);

    if(strcmp(i_attrname,"NULL")==0)  i_attrname = NULL;
    o_rtn_val = HE5_PTinqdatatype(i_ptid, i_levelname, i_attrname, i_group, &i_datatype, &o_classid, &o_order, &o_size);
    if(o_rtn_val == FAIL) return Qfalse;
    classid = INT2NUM(o_classid);
    order = INT2NUM(o_order);
    size = INT2NUM(o_size);

    return rb_ary_new3(3, classid, order, size);
}

VALUE
hdfeos5_ptinqpoint(VALUE mod)
{
    char *i_filename;
    char *o_pointlist;
    long o_strbufsize;
    long o_nPoint;
    VALUE nPoint;
    VALUE pointlist;
    VALUE strbufsize;

    struct HE5 *he5file;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5, he5file);
    i_filename=he5file->name;

    o_nPoint = HE5_PTinqpoint(i_filename, NULL, &o_strbufsize);
    if (o_nPoint < 0 ) return  Qfalse ;

    o_pointlist = ALLOCA_N(char, (o_strbufsize + 1)*sizeof(char));
    o_nPoint = HE5_PTinqpoint(i_filename, o_pointlist, &o_strbufsize);
    if (o_nPoint < 0 ) return  Qfalse ;
    else               nPoint = LONG2NUM(o_nPoint);
    pointlist = rb_str_new(o_pointlist,o_strbufsize);
    strbufsize = LONG2NUM(o_strbufsize);

    return rb_ary_new3(3, nPoint, pointlist, strbufsize);
}

VALUE
hdfeos5_ptinqattrs(VALUE mod)
{
    hid_t i_ptid;
    char *o_attrnames;
    long  o_strbufsize;
    long  o_number;
    VALUE nattr;
    VALUE attrnames;
    VALUE strbufsize;

    struct HE5Pt *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Pt, he5point);
    i_ptid=he5point->ptid;

    o_number = HE5_PTinqattrs(i_ptid, NULL, &o_strbufsize);
    if(o_number == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    o_attrnames = ALLOCA_N(char, (o_strbufsize + 1)*sizeof(char));

    o_number = HE5_PTinqattrs(i_ptid, o_attrnames, &o_strbufsize);
    if(o_number == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    nattr = LONG2NUM(o_number);
    attrnames = rb_str_new(o_attrnames,o_strbufsize);
    strbufsize = INT2NUM(o_strbufsize);

    return rb_ary_new3(3, nattr, attrnames, strbufsize);
}

VALUE
hdfeos5_ptwritegrpattr(VALUE mod, VALUE attrname, VALUE numbertype, VALUE count, VALUE datbuf)
{
    hid_t i_ptid;
    char *i_attrname;
    hid_t i_numbertype;
    hid_t i_numbertypechk;
    unsigned long long *i_count;
    void *i_datbuf;
    herr_t o_rtn_val;
    VALUE rtn_val;

    struct HE5Pt *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Pt, he5point);
    i_ptid=he5point->ptid;

    Check_Type(attrname,T_STRING);
    SafeStringValue(attrname);
    Check_Type(numbertype,T_STRING);
    SafeStringValue(numbertype);
    count = rb_Array(count);

    i_attrname = RSTRING_PTR(attrname);
    i_numbertype    = change_numbertype(RSTRING_PTR(numbertype));
    i_numbertypechk = check_numbertype(RSTRING_PTR(numbertype));
    i_count = hdfeos5_obj2cunsint64ary(count);

    HE5Wrap_store_NArray1D_or_str(i_numbertypechk, datbuf, &i_datbuf); 
    o_rtn_val = HE5_PTwritegrpattr(i_ptid, i_attrname, i_numbertype, i_count, i_datbuf);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;
    hdfeos5_freecunsint64ary(i_count);
    return(rtn_val);
}

VALUE
hdfeos5_pt_get_grpatt(VALUE mod, VALUE attrname)
{
    VALUE result;
    hid_t i_ptid;
    char *i_attrname;
    hid_t o_ntype;
    void *o_datbuf;
    unsigned long long o_count;
    herr_t o_rtn_val;

    struct HE5Pt *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Pt, he5point);
    i_ptid=he5point->ptid;

    Check_Type(attrname,T_STRING);
    SafeStringValue(attrname);
    i_attrname = RSTRING_PTR(attrname);

    o_rtn_val = HE5_PTgrpattrinfo(i_ptid, i_attrname, &o_ntype, &o_count);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    HE5Wrap_make_NArray1D_or_str(o_ntype, o_count, &result, &o_datbuf);
    o_rtn_val = HE5_PTreadgrpattr(i_ptid, i_attrname, o_datbuf);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    return result;
}

VALUE
hdfeos5_ptinqgrpattrs(VALUE mod)
{
    hid_t i_ptid;
    char *o_attrname;
    long o_strbufsize;
    long o_nattr;
    VALUE nattr;
    VALUE attrname;
    VALUE strbufsize;

    struct HE5Pt *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Pt, he5point);
    i_ptid=he5point->ptid;

    o_nattr = HE5_PTinqgrpattrs(i_ptid, NULL, &o_strbufsize);
    if(o_nattr == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    o_attrname = ALLOCA_N(char, (o_strbufsize + 1)*sizeof(char));

    o_nattr = HE5_PTinqgrpattrs(i_ptid, o_attrname, &o_strbufsize);
    if(o_nattr == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    nattr = LONG2NUM(o_nattr);
    attrname = rb_str_new(o_attrname,o_strbufsize);
    strbufsize = INT2NUM(o_strbufsize);
    return rb_ary_new3(3, nattr, attrname, strbufsize);
}

VALUE
hdfeos5_ptwritelocattr(VALUE mod, VALUE attrname, VALUE numbertype, VALUE count, VALUE datbuf)
{
    hid_t i_ptid;
    char *i_levelname;
    char *i_attrname;
    hid_t i_numbertype;
    hid_t i_numbertypechk;
    unsigned long long *i_count;
    void *i_datbuf;
    herr_t o_rtn_val;
    VALUE rtn_val;

    struct HE5PtField *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5PtField, he5point);
    i_levelname=he5point->levelname;
    i_ptid=he5point->ptid;

    Check_Type(attrname,T_STRING);
    SafeStringValue(attrname);
    Check_Type(numbertype,T_STRING);
    SafeStringValue(numbertype);
    count = rb_Array(count);

    i_attrname = RSTRING_PTR(attrname);
    i_numbertype    = change_numbertype(RSTRING_PTR(numbertype));
    i_numbertypechk = check_numbertype(RSTRING_PTR(numbertype));
    i_count = hdfeos5_obj2cunsint64ary(count);

    HE5Wrap_store_NArray1D_or_str(i_numbertypechk, datbuf, &i_datbuf); 
    o_rtn_val = HE5_PTwritelocattr(i_ptid, i_levelname, i_attrname, i_numbertype, i_count, i_datbuf);
    rtn_val = (o_rtn_val == FAIL) ? Qfalse : Qtrue;
    hdfeos5_freecintary((int*)i_count);
    return rtn_val;
}

VALUE
hdfeos5_ptfield_get_att(VALUE mod,VALUE  attrname)
{
    VALUE result;
    hid_t i_ptid;
    char *i_levelname;
    char *i_attrname;
    void *o_datbuf;
    herr_t o_rtn_val;
    hid_t  o_ntype;
    unsigned long long o_count;

    struct HE5PtField *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5PtField, he5point);
    i_levelname=he5point->levelname;
    i_ptid=he5point->ptid;
    Check_Type(attrname,T_STRING);
    SafeStringValue(attrname);
    i_attrname = RSTRING_PTR(attrname);

    o_rtn_val = HE5_PTlocattrinfo(i_ptid, i_levelname, i_attrname, 
				  &o_ntype, &o_count);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",
				   __FILE__,__LINE__);

    HE5Wrap_make_NArray1D_or_str(o_ntype, o_count, &result, &o_datbuf);
    o_rtn_val = HE5_PTreadlocattr(i_ptid, i_levelname,i_attrname, o_datbuf);
    if(o_rtn_val == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",
				   __FILE__,__LINE__);
    return result;
}

VALUE
hdfeos5_ptinqlocattrs(VALUE mod)
{
    hid_t i_ptid;
    char *i_levelname;
    char *o_attrnames;
    long o_strbufsize;
    long o_nattr;
    VALUE nattr;
    VALUE attrname;
    VALUE strbufsize;

    struct HE5PtField *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5PtField, he5point);
    i_levelname=he5point->levelname;
    i_ptid=he5point->ptid;

    o_nattr = HE5_PTinqlocattrs(i_ptid, i_levelname, NULL, &o_strbufsize);
    if(o_nattr == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]", __FILE__,__LINE__);
 
    o_attrnames = ALLOCA_N(char, (o_strbufsize + 1)*sizeof(char));
    o_nattr = HE5_PTinqlocattrs(i_ptid, i_levelname, o_attrnames, &o_strbufsize);
    if(o_nattr == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]", __FILE__,__LINE__);
    nattr = LONG2NUM(o_nattr);
    attrname = rb_str_new(o_attrnames,o_strbufsize);
    strbufsize = LONG2NUM(o_strbufsize);
    return rb_ary_new3(3, nattr, attrname, strbufsize);
}

VALUE
hdfeos5_ptbcklinkinfo(VALUE mod)
{
    int i_ptid;
    herr_t status;
    int i_level;
    char *i_levelname;
    char o_linkfield[HE5_BLKSIZE];
    struct HE5PtField *he5point;
    VALUE linkfield;

    rb_secure(4);
    Data_Get_Struct(mod, struct HE5PtField, he5point);
    i_ptid=he5point->ptid;
    i_levelname=he5point->levelname;

    i_level=HE5_PTlevelindx( i_ptid, i_levelname);
    if(i_level < 0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    status = HE5_PTbcklinkinfo(i_ptid, i_level, o_linkfield);
    if( status < 0 ) return Qnil;
    linkfield = rb_str_new2(o_linkfield);
    return linkfield;
}

VALUE
hdfeos5_ptfwdlinkinfo(VALUE mod)
{
    int i_ptid;
    herr_t status;
    int i_level;
    char *i_levelname;
    char o_linkfield[HE5_BLKSIZE];
    struct HE5PtField *he5point;
    VALUE linkfield;

    rb_secure(4);
    Data_Get_Struct(mod, struct HE5PtField, he5point);
    i_ptid=he5point->ptid;
    i_levelname=he5point->levelname;

    i_level=HE5_PTlevelindx( i_ptid, i_levelname);
    if(i_level < 0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    status = HE5_PTfwdlinkinfo(i_ptid, i_level, o_linkfield);
    if( status < 0 ) return Qnil;
    linkfield = rb_str_new2(o_linkfield);
    return linkfield;
}

VALUE
hdfeos5_ptlevelindx(VALUE mod)
{
    hid_t i_ptid;
    char *i_levelname;
    long  o_level;
    VALUE levelnumber;

    struct HE5PtField *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5PtField, he5point);
    i_levelname=he5point->levelname;
    i_ptid=he5point->ptid;

    o_level = HE5_PTlevelindx(i_ptid, i_levelname);
    if(o_level < 0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    levelnumber = INT2NUM(o_level);
    return rb_ary_new2(levelnumber);
}

VALUE
hdfeos5_ptupdatelevel(VALUE mod, VALUE nrec, VALUE recs, VALUE data, VALUE ntype)
{
    char *chk_ntype;
    Check_Type(ntype,T_STRING);
    SafeStringValue(ntype);
    chk_ntype = RSTRING_PTR(ntype);

    switch (check_numbertype(chk_ntype)){
    case  HE5T_NATIVE_CHAR:
    case  HE5T_NATIVE_SCHAR:
    case  HE5T_NATIVE_UCHAR:
    case  HE5T_CHARSTRING:
        return hdfeos5_ptupdatelevel_char(mod, nrec, recs, data);
	break;

    case  HE5T_NATIVE_INT8:
    case  HE5T_NATIVE_UINT8:
        return hdfeos5_ptupdatelevel_char(mod, nrec, recs, data);
	break;

    case  HE5T_NATIVE_SHORT:
    case  HE5T_NATIVE_USHORT:
    case  HE5T_NATIVE_INT16:
    case  HE5T_NATIVE_UINT16:
        return hdfeos5_ptupdatelevel_short(mod, nrec, recs, data);
	break;

    case  HE5T_NATIVE_INT:
    case  HE5T_NATIVE_UINT:
    case  HE5T_NATIVE_INT32:
    case  HE5T_NATIVE_UINT32:
        return hdfeos5_ptupdatelevel_int(mod, nrec, recs, data);
	break;

    case  HE5T_NATIVE_LONG:
        return hdfeos5_ptupdatelevel_long(mod, nrec, recs, data);
	break;

    case  HE5T_NATIVE_FLOAT:
        return hdfeos5_ptupdatelevel_float(mod, nrec, recs, data);
	break;

    case  HE5T_NATIVE_DOUBLE:
        return hdfeos5_ptupdatelevel_double(mod, nrec, recs, data);
	break;
    default:
	rb_raise(rb_eHE5Error, "not match data type [%s:%d]",__FILE__,__LINE__);
    }
}

VALUE
hdfeos5_ptchkpoint(VALUE mod)
{
    char *i_filename;
    long o_strbufsize;
    long o_rtn_val;

    struct HE5 *he5file;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5, he5file);
    i_filename=he5file->name;

    o_rtn_val = HE5_PTinqpoint(i_filename, NULL, &o_strbufsize);
    if( o_rtn_val <= 0) return Qfalse;
    return Qtrue;
}

VALUE
hdfeos5_ptchkpointname(VALUE mod)
{
    char *i_filename;
    char *o_pointlist;
    long o_strbufsize;
    long o_rtn_val;
    VALUE rstr;

    struct HE5 *he5file;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5, he5file);
    i_filename=he5file->name;

    o_rtn_val = HE5_PTinqpoint(i_filename, NULL, &o_strbufsize);
    if( o_rtn_val <= 0) return Qfalse;
    o_pointlist = ALLOCA_N(char, (o_strbufsize + 1));
    
    o_rtn_val = HE5_PTinqpoint(i_filename, o_pointlist, &o_strbufsize);
    if( o_rtn_val <= 0) return Qfalse;
    rstr = rb_str_new(o_pointlist, o_strbufsize);
    return rstr;
}

VALUE
hdfeos5_ptchkfieldname(VALUE mod,VALUE levelname)
{
    int i_ptid;
    int o_level;
    int o_nflds;
    char *o_fieldlist;
    char *i_levelname;
    long o_strbufsize;
    struct HE5Pt *he5pt;
    VALUE fieldlist;

    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Pt, he5pt);
    i_ptid=he5pt->ptid;

    Check_Type(levelname,T_STRING);
    SafeStringValue(levelname);
    i_levelname = RSTRING_PTR(levelname);

    o_level=HE5_PTlevelindx(i_ptid, i_levelname);
    if(o_level < 0 ) rb_raise(rb_eHE5Error, "ERROR [%s:%d],__FILE__,__LINE__");

    o_nflds = HE5_PTnfields(i_ptid, o_level, NULL, &o_strbufsize);
    if(o_nflds < 0 ) rb_raise(rb_eHE5Error, "ERROR [%s:%d],__FILE__,__LINE__");
    o_fieldlist = ALLOC_N(char,(o_strbufsize+1)*sizeof(char));
    o_nflds = HE5_PTnfields(i_ptid, o_level, o_fieldlist, &o_strbufsize);
    if(o_nflds < 0 ) rb_raise(rb_eHE5Error, "ERROR [%s:%d],__FILE__,__LINE__");

    fieldlist = rb_str_new(o_fieldlist,o_strbufsize);
    return(fieldlist);
}

VALUE
hdfeos5_ptsetfield(VALUE mod,VALUE fieldname)
{
    int i_ptid;
    char *i_fieldname;
    char *i_levelname;
    long o_strbufsize;
    struct HE5Pt *he5pt;
    struct HE5PtField *he5point;

    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Pt, he5pt);
    i_ptid=he5pt->ptid;

    Check_Type(fieldname,T_STRING);
    SafeStringValue(fieldname);
    i_fieldname = RSTRING_PTR(fieldname);

    o_strbufsize = search_levelsize(i_ptid,i_fieldname);
    i_levelname  = ALLOCA_N(char,o_strbufsize+1);
    i_levelname  = search_levelname(i_ptid,i_fieldname);

    he5point = HE5PtField_init(i_fieldname, i_levelname, i_ptid, mod);
    return(Data_Wrap_Struct(cHE5PtField, he5ptfield_mark_obj, HE5PtField_free, he5point));
}              

VALUE
hdfeos5_ptsetfield_level(VALUE mod,VALUE fieldname,VALUE levelname)
{
    int i_ptid;
    char *i_fieldname;
    char *i_levelname;
    struct HE5Pt *he5pt;
    struct HE5PtField *he5point;

    rb_secure(4);
    Data_Get_Struct(mod, struct HE5Pt, he5pt);
    i_ptid=he5pt->ptid;

    Check_Type(fieldname,T_STRING);
    SafeStringValue(fieldname);
    i_fieldname = RSTRING_PTR(fieldname);
    i_levelname = RSTRING_PTR(levelname);

    he5point = HE5PtField_init(i_fieldname, i_levelname, i_ptid, mod);
    return(Data_Wrap_Struct(cHE5PtField, he5ptfield_mark_obj, HE5PtField_free, he5point));
}

VALUE
hdfeos5_ptgetfield(VALUE mod)
{
    char *i_fieldname;
    struct HE5PtField *he5point;

    rb_secure(4);
    Data_Get_Struct(mod, struct HE5PtField, he5point);
    i_fieldname=he5point->name;

    return rb_str_new2(i_fieldname);
}

VALUE 
hdfeos5_pt_whether_in_define_mode(VALUE pt)
{
    int fid;
    hid_t HDFfid = FAIL;
    hid_t gid = FAIL;
    uintn access = 0;
    int status;
    struct HE5Pt *he5point;

    Data_Get_Struct(pt, struct HE5Pt, he5point);
    fid=he5point->fid;

    status = HE5_EHchkfid(fid, "HE5_PTcreate", &HDFfid,  &gid, &access);
    if(status != FAIL){
      return Qtrue;
    }else {
      status = HE5_EHchkfid(fid, "HE5_PTattach", &HDFfid,  &gid, &access);
      if(status != FAIL){
        return Qtrue;
      } else {
        return Qnil;
      }
    }
}

VALUE
hdfeos5_pt_path(VALUE pt)
{
    char *i_name;
    struct HE5Pt *he5point;
  
    Data_Get_Struct(pt, struct HE5Pt, he5point);

    i_name=he5point->name;
    return rb_str_new2(i_name);
}

VALUE
hdfeos5_pt_inqname(VALUE pt)
{
    char *i_name;
    struct HE5Pt *he5point;
  
    Data_Get_Struct(pt, struct HE5Pt, he5point);

    i_name=he5point->name;
    return rb_str_new2(i_name);
}

VALUE
hdfeos5_pt_file(VALUE pt)
{
    struct HE5Pt *he5point;
  
    rb_secure(4);
    Data_Get_Struct(pt, struct HE5Pt, he5point);
    return(he5point->file);
}

VALUE
hdfeos5_level_point(VALUE field)
{
    struct HE5PtField *he5point;

    rb_secure(4);
    Data_Get_Struct(field, struct HE5PtField, he5point);
    return(he5point->point);
}

VALUE
hdfeos5_level_inqname(VALUE level)
{
    char *i_name;
    struct HE5PtField *he5point;

    rb_secure(4);
    Data_Get_Struct(level, struct HE5PtField, he5point);

    i_name=he5point->name;
    return rb_str_new2(i_name);
}

VALUE
hdfeos5_ptwritelevel_char(VALUE mod, VALUE count, VALUE data)
{
    hid_t i_ptid;
    char *i_levelname;
    char *i_fieldname;
    long *i_count;
    int  i_level;
    int  i_ntype;

    int  len;
    int  *shape;    /* NArray uses int instead of size_t */
    herr_t status;
    unsigned char *i_data;

    struct HE5PtField *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5PtField, he5point);
    i_fieldname=he5point->name;
    i_levelname=he5point->levelname;
    i_ptid=he5point->ptid;

    Array_to_Cbyte_len_shape(data,i_data,len,shape);
    i_ntype=check_numbertype("char");

    i_count = hdfeos5_obj2clongary(count);
    i_level=HE5_PTlevelindx(i_ptid, i_levelname);
    if(i_level <0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    status = HE5_PTwritelevelF(i_ptid, i_level, i_count, i_fieldname, i_ntype, i_data);
    hdfeos5_freeclongary(i_count);
    if(status != FAIL) return status;
    return Qnil;
}

VALUE
hdfeos5_ptwritelevel_int(VALUE mod, VALUE count, VALUE data)
{
    hid_t i_ptid;
    char *i_levelname;
    char *i_fieldname;
    long *i_count;
    int  i_level;
    int  i_ntype;

    int  len;
    int  *shape;    /* NArray uses int instead of size_t */
    herr_t status;
    int *i_data;

    struct HE5PtField *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5PtField, he5point);
    i_levelname=he5point->levelname;
    i_fieldname=he5point->name;
    i_ptid=he5point->ptid;

    i_count = hdfeos5_obj2clongary(count);
    i_level=HE5_PTlevelindx(i_ptid, i_levelname);
    if(i_level <0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    Array_to_Clint_len_shape(data,i_data,len,shape);
    i_ntype=check_numbertype("int");

    status = HE5_PTwritelevelF(i_ptid, i_level, i_count, i_fieldname, i_ntype, i_data);
    hdfeos5_freeclongary(i_count);
    if(status != FAIL) return status;
    return Qnil;
}

VALUE
hdfeos5_ptwritelevel_short(VALUE mod, VALUE count, VALUE data)
{
    hid_t i_ptid;
    char *i_levelname;
    char *i_fieldname;
    long *i_count;
    int  i_level;
    int  i_ntype;

    int  len;
    int  *shape;    /* NArray uses int instead of size_t */
    herr_t status;
    short *i_data;

    struct HE5PtField *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5PtField, he5point);
    i_levelname=he5point->levelname;
    i_fieldname=he5point->name;
    i_ptid=he5point->ptid;

    i_count = hdfeos5_obj2clongary(count);
    i_level=HE5_PTlevelindx(i_ptid, i_levelname);
    if(i_level <0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    Array_to_Cint_len_shape(data,i_data,len,shape);
    i_ntype=check_numbertype("short");

    status = HE5_PTwritelevelF(i_ptid, i_level, i_count, i_fieldname, i_ntype, i_data);
    hdfeos5_freeclongary(i_count);
    if(status != FAIL) return status;
    return Qnil;
}

VALUE
hdfeos5_ptwritelevel_long(VALUE mod, VALUE count, VALUE data)
{
    hid_t i_ptid;
    char *i_levelname;
    char *i_fieldname;
    long *i_count;
    int  i_level;
    int  i_ntype;

    int  len;
    int  *shape;    /* NArray uses int instead of size_t */
    herr_t status;
    long *i_data;

    struct HE5PtField *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5PtField, he5point);
    i_levelname=he5point->levelname;
    i_fieldname=he5point->name;
    i_ptid=he5point->ptid;

    i_count = hdfeos5_obj2clongary(count);
    i_level=HE5_PTlevelindx(i_ptid, i_levelname);
    if(i_level <0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    Array_to_Clong_len_shape(data,i_data,len,shape);
    i_ntype=check_numbertype("long");

    status = HE5_PTwritelevelF(i_ptid, i_level, i_count, i_fieldname, i_ntype, i_data);
    hdfeos5_freeclongary(i_count);
    if(status != FAIL) return status;
    return Qnil;
}

VALUE
hdfeos5_ptwritelevel_float(VALUE mod, VALUE count, VALUE data)
{
    hid_t i_ptid;
    char *i_levelname;
    char *i_fieldname;
    long *i_count;
    int  i_level;
    int  i_ntype;

    int  len;
    int  *shape;    /* NArray uses int instead of size_t */
    herr_t status;
    float *i_data;

    struct HE5PtField *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5PtField, he5point);
    i_levelname=he5point->levelname;
    i_fieldname=he5point->name;
    i_ptid=he5point->ptid;

    i_count = hdfeos5_obj2clongary(count);
    i_level=HE5_PTlevelindx(i_ptid, i_levelname);
    if(i_level <0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    Array_to_Cfloat_len_shape(data,i_data,len,shape);
    i_ntype=check_numbertype("sfloat");

    status = HE5_PTwritelevelF(i_ptid, i_level, i_count, i_fieldname, i_ntype, i_data);
    hdfeos5_freeclongary(i_count);
    if(status != FAIL) return status;
    return Qnil;
}

VALUE
hdfeos5_ptwritelevel_double(VALUE mod, VALUE count, VALUE data)
{
    hid_t i_ptid;
    char *i_levelname;
    char *i_fieldname;
    long *i_count;
    int  i_level;
    int  i_ntype;

    int  len;
    int  *shape;    /* NArray uses int instead of size_t */
    herr_t status;
    double *i_data;

    struct HE5PtField *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5PtField, he5point);
    i_levelname=he5point->levelname;
    i_fieldname=he5point->name;
    i_ptid=he5point->ptid;

    i_count = hdfeos5_obj2clongary(count);
    i_level=HE5_PTlevelindx(i_ptid, i_levelname);
    if(i_level <0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    Array_to_Cdouble_len_shape(data,i_data,len,shape);
    i_ntype=check_numbertype("float");

    status = HE5_PTwritelevelF(i_ptid, i_level, i_count, i_fieldname, i_ntype, i_data);
    hdfeos5_freeclongary(i_count);
    if(status != FAIL) return status;
    return Qnil;
}

VALUE
hdfeos5_ptreadlevel_char(VALUE mod)
{
    hid_t i_ptid;
    char *i_levelname;
    char *i_fieldname;
    int  i_level;
    int  i_ntype=56;
    int  i_nrecs;
    int  i_rank=1;

    int  i;
    int  *shape;    /* NArray uses int instead of size_t */
    int  *shape_child;    /* NArray uses int instead of size_t */
    char o_linkfield[HE5_BLKSIZE];
    unsigned char *o_data;
    unsigned char *o_data_new;
    herr_t status;
    VALUE NArray;

    HE5_CmpDTSinfo    dtsinfo;

    struct HE5PtField *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5PtField, he5point);
    i_levelname=he5point->levelname;
    i_fieldname=he5point->name;
    i_ptid=he5point->ptid;

    i_level=HE5_PTlevelindx(i_ptid, i_levelname);
    i_nrecs=HE5_PTnrecs(i_ptid, i_level);
    if(i_level <0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    status = HE5_PTlevelinfo(i_ptid, i_level, &dtsinfo); 
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    for(i=0;i<dtsinfo.nfields;i++) {
       if(strcmp(i_fieldname,dtsinfo.fieldname[i])==0){
          i_rank=dtsinfo.rank[i];
          i_ntype=dtsinfo.numtype[i];
       }
    }
    shape = ALLOCA_N(int,i_rank);
    for(i=0;i<i_rank;i++){
      shape[i_rank-1-i]=i_nrecs;
    }
    Cbyte_to_NArray(NArray,i_rank,shape,o_data);

    status = HE5_PTreadlevelF(i_ptid, i_level, i_fieldname, i_ntype, o_data);
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

// linkage check start
    status = HE5_PTfwdlinkinfo(i_ptid, i_level, o_linkfield);
    if( status !=FAIL ) {

       // parent level field 
       for(i=0;i<dtsinfo.nfields;i++) {
          if(strcmp(o_linkfield,dtsinfo.fieldname[i])==0){
             i_ntype=dtsinfo.numtype[i];
          }
       }
       // child level field 
       i_nrecs=HE5_PTnrecs(i_ptid, i_level+1);
       for(i=0;i<i_rank;i++){
         shape[i_rank-1-i]=i_nrecs;
       }
       Cbyte_to_NArray(NArray,i_rank,shape,o_data_new);
       shape_child=ALLOCA_N(int,i_nrecs);

       // set pointer
       switch (i_ntype){
       case  HE5T_NATIVE_INT8:
       case  HE5T_NATIVE_UINT8:
           sort_data_byte(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       case  HE5T_NATIVE_SHORT:
       case  HE5T_NATIVE_USHORT:
       case  HE5T_NATIVE_INT16:
       case  HE5T_NATIVE_UINT16:
           sort_data_short(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       case  HE5T_NATIVE_INT:
       case  HE5T_NATIVE_UINT:
       case  HE5T_NATIVE_INT32:
       case  HE5T_NATIVE_UINT32:
           sort_data_int(i_ptid, i_level, o_linkfield, shape_child);
 	   break;
       case  HE5T_NATIVE_LONG:
           sort_data_long(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       case  HE5T_NATIVE_FLOAT:
           sort_data_float(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       case  HE5T_NATIVE_DOUBLE:
           sort_data_double(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       default:
	   rb_raise(rb_eHE5Error, "Sorry, number type %d is yet to be supoorted [%s:%d]",
		 i_ntype,__FILE__,__LINE__);
       }
       for(i=0;i<i_nrecs;++i){
          *(char *)&o_data_new[i] = *(char *)&o_data[*(int *)&shape_child[i]];
       }
    }
// linkage check
    OBJ_TAINT(NArray);

    return(NArray);
}

VALUE
hdfeos5_ptreadlevel_short(VALUE mod)
{
    hid_t i_ptid;
    char *i_levelname;
    char *i_fieldname;
    int  i_level;
    int  i_nrecs;
    int  i_ntype=2;
    int  i_rank=1;

    int  i;
    int  *shape;    /* NArray uses int instead of size_t */
    int  *shape_child;    /* NArray uses int instead of size_t */
    char o_linkfield[HE5_BLKSIZE];
    short *o_data;
    short *o_data_new;
    herr_t status;
    VALUE NArray;

    HE5_CmpDTSinfo    dtsinfo;

    struct HE5PtField *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5PtField, he5point);
    i_levelname=he5point->levelname;
    i_fieldname=he5point->name;
    i_ptid=he5point->ptid;

    i_level=HE5_PTlevelindx(i_ptid, i_levelname);
    i_nrecs=HE5_PTnrecs(i_ptid, i_level);
    if(i_level <0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    status = HE5_PTlevelinfo(i_ptid, i_level, &dtsinfo); 
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    for(i=0;i<dtsinfo.nfields;i++) {
       if(strcmp(i_fieldname,dtsinfo.fieldname[i])==0){
          i_rank=dtsinfo.rank[i];
          i_ntype=dtsinfo.numtype[i];
       }
    }
    shape = ALLOCA_N(int,i_rank);
    for(i=0;i<i_rank;i++){
      shape[i_rank-1-i]=i_nrecs;
    }
    Cint_to_NArray(NArray,i_rank,shape,o_data);

    status = HE5_PTreadlevelF(i_ptid, i_level, i_fieldname, i_ntype, o_data);
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

// linkage check start
    status = HE5_PTfwdlinkinfo(i_ptid, i_level, o_linkfield);
    if( status !=FAIL ) {

       // parent level field 
       for(i=0;i<dtsinfo.nfields;i++) {
          if(strcmp(o_linkfield,dtsinfo.fieldname[i])==0){
             i_ntype=dtsinfo.numtype[i];
          }
       }
       // child level field 
       i_nrecs=HE5_PTnrecs(i_ptid, i_level+1);
       for(i=0;i<i_rank;i++){
         shape[i_rank-1-i]=i_nrecs;
       }
       Cint_to_NArray(NArray,i_rank,shape,o_data_new);
       shape_child=ALLOCA_N(int,i_nrecs);

       // set pointer
       switch (i_ntype){
       case  HE5T_NATIVE_INT8:
       case  HE5T_NATIVE_UINT8:
           sort_data_byte(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       case  HE5T_NATIVE_SHORT:
       case  HE5T_NATIVE_USHORT:
       case  HE5T_NATIVE_INT16:
       case  HE5T_NATIVE_UINT16:
           sort_data_short(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       case  HE5T_NATIVE_INT:
       case  HE5T_NATIVE_UINT:
       case  HE5T_NATIVE_INT32:
       case  HE5T_NATIVE_UINT32:
           sort_data_int(i_ptid, i_level, o_linkfield, shape_child);
 	   break;
       case  HE5T_NATIVE_LONG:
           sort_data_long(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       case  HE5T_NATIVE_FLOAT:
           sort_data_float(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       case  HE5T_NATIVE_DOUBLE:
           sort_data_double(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       default:
	   rb_raise(rb_eHE5Error, "Sorry, number type %d is yet to be supoorted [%s:%d]",
		 i_ntype,__FILE__,__LINE__);
       }
       for(i=0;i<i_nrecs;++i){
          *(short *)&o_data_new[i] = *(short *)&o_data[*(int *)&shape_child[i]];
       }
    }
// linkage check
    OBJ_TAINT(NArray);

    return(NArray);
}

VALUE
hdfeos5_ptreadlevel_int(VALUE mod)
{
    hid_t i_ptid;
    char *i_levelname;
    char *i_fieldname;
    int  i_level;
    int  i_ntype=0;
    int  i_nrecs;
    int  i_rank=1;

    int  i;
    int  *shape;    /* NArray uses int instead of size_t */
    int  *shape_child;    /* NArray uses int instead of size_t */
    char o_linkfield[HE5_BLKSIZE];
    int *o_data;
    int *o_data_new;
    herr_t status;
    VALUE NArray;

    HE5_CmpDTSinfo    dtsinfo;

    struct HE5PtField *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5PtField, he5point);
    i_levelname=he5point->levelname;
    i_fieldname=he5point->name;
    i_ptid=he5point->ptid;

    i_level=HE5_PTlevelindx(i_ptid, i_levelname);
    i_nrecs=HE5_PTnrecs(i_ptid, i_level);
    if(i_level <0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    status = HE5_PTlevelinfo(i_ptid, i_level, &dtsinfo); 
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    for(i=0;i<dtsinfo.nfields;i++) {
       if(strcmp(i_fieldname,dtsinfo.fieldname[i])==0){
          i_rank=dtsinfo.rank[i];
          i_ntype=dtsinfo.numtype[i];
       }
    }
    shape = ALLOCA_N(int,i_rank);
    for(i=0;i<i_rank;i++){
      shape[i_rank-1-i]=i_nrecs;
    }
    Clint_to_NArray(NArray,i_rank,shape,o_data);

    status = HE5_PTreadlevelF(i_ptid, i_level, i_fieldname, i_ntype, o_data);
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

// linkage check start
    status = HE5_PTfwdlinkinfo(i_ptid, i_level, o_linkfield);
    if( status !=FAIL ) {

       // parent level field 
       for(i=0;i<dtsinfo.nfields;i++) {
          if(strcmp(o_linkfield,dtsinfo.fieldname[i])==0){
             i_ntype=dtsinfo.numtype[i];
          }
       }
       // child level field 
       i_nrecs=HE5_PTnrecs(i_ptid, i_level+1);
       for(i=0;i<i_rank;i++){
         shape[i_rank-1-i]=i_nrecs;
       }
       Clint_to_NArray(NArray,i_rank,shape,o_data_new);
       shape_child=ALLOCA_N(int,i_nrecs);

       // set pointer
       switch (i_ntype){
       case  HE5T_NATIVE_INT8:
       case  HE5T_NATIVE_UINT8:
           sort_data_byte(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       case  HE5T_NATIVE_SHORT:
       case  HE5T_NATIVE_USHORT:
       case  HE5T_NATIVE_INT16:
       case  HE5T_NATIVE_UINT16:
           sort_data_short(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       case  HE5T_NATIVE_INT:
       case  HE5T_NATIVE_UINT:
       case  HE5T_NATIVE_INT32:
       case  HE5T_NATIVE_UINT32:
           sort_data_int(i_ptid, i_level, o_linkfield, shape_child);
 	   break;
       case  HE5T_NATIVE_LONG:
           sort_data_long(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       case  HE5T_NATIVE_FLOAT:
           sort_data_float(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       case  HE5T_NATIVE_DOUBLE:
           sort_data_double(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       default:
	   rb_raise(rb_eHE5Error, "Sorry, number type %d is yet to be supoorted [%s:%d]",
		 i_ntype,__FILE__,__LINE__);
       }
       for(i=0;i<i_nrecs;++i){
          *(int *)&o_data_new[i] = *(int *)&o_data[*(int *)&shape_child[i]];
       }
    }
// linkage check
    OBJ_TAINT(NArray);

    return(NArray);
}

VALUE
hdfeos5_ptreadlevel_long(VALUE mod)
{
    hid_t i_ptid;
    char *i_levelname;
    char *i_fieldname;
    int  i_level;
    int  i_ntype=6;
    int  i_nrecs;
    int  i_rank=1;

    int  i;
    int  *shape;    /* NArray uses int instead of size_t */
    int  *shape_child;    /* NArray uses int instead of size_t */
    char o_linkfield[HE5_BLKSIZE];
    long *o_data;
    long *o_data_new;
    herr_t status;
    VALUE NArray;

    HE5_CmpDTSinfo    dtsinfo;

    struct HE5PtField *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5PtField, he5point);
    i_levelname=he5point->levelname;
    i_fieldname=he5point->name;
    i_ptid=he5point->ptid;

    i_level=HE5_PTlevelindx(i_ptid, i_levelname);
    i_nrecs=HE5_PTnrecs(i_ptid, i_level);
    if(i_level <0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    status = HE5_PTlevelinfo(i_ptid, i_level, &dtsinfo); 
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    for(i=0;i<dtsinfo.nfields;i++) {
       if(strcmp(i_fieldname,dtsinfo.fieldname[i])==0){
          i_rank=dtsinfo.rank[i];
          i_ntype=dtsinfo.numtype[i];
       }
    }
    shape = ALLOCA_N(int,i_rank);
    for(i=0;i<i_rank;i++){
      shape[i_rank-1-i]=i_nrecs;
    }
    Clong_to_NArray(NArray,i_rank,shape,o_data);

    status = HE5_PTreadlevelF(i_ptid, i_level, i_fieldname, i_ntype, o_data);
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

// linkage check start
    status = HE5_PTfwdlinkinfo(i_ptid, i_level, o_linkfield);
    if( status !=FAIL ) {

       // parent level field 
       for(i=0;i<dtsinfo.nfields;i++) {
          if(strcmp(o_linkfield,dtsinfo.fieldname[i])==0){
             i_ntype=dtsinfo.numtype[i];
          }
       }
       // child level field 
       i_nrecs=HE5_PTnrecs(i_ptid, i_level+1);
       for(i=0;i<i_rank;i++){
         shape[i_rank-1-i]=i_nrecs;
       }
       Clong_to_NArray(NArray,i_rank,shape,o_data_new);
       shape_child=ALLOCA_N(int,i_nrecs);

       // set pointer
       switch (i_ntype){
       case  HE5T_NATIVE_INT8:
       case  HE5T_NATIVE_UINT8:
           sort_data_byte(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       case  HE5T_NATIVE_SHORT:
       case  HE5T_NATIVE_USHORT:
       case  HE5T_NATIVE_INT16:
       case  HE5T_NATIVE_UINT16:
           sort_data_short(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       case  HE5T_NATIVE_INT:
       case  HE5T_NATIVE_UINT:
       case  HE5T_NATIVE_INT32:
       case  HE5T_NATIVE_UINT32:
           sort_data_int(i_ptid, i_level, o_linkfield, shape_child);
 	   break;
       case  HE5T_NATIVE_LONG:
           sort_data_long(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       case  HE5T_NATIVE_FLOAT:
           sort_data_float(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       case  HE5T_NATIVE_DOUBLE:
           sort_data_double(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       default:
	   rb_raise(rb_eHE5Error, "Sorry, number type %d is yet to be supoorted [%s:%d]",
		 i_ntype,__FILE__,__LINE__);
       }
       for(i=0;i<i_nrecs;++i){
          *(long *)&o_data_new[i] = *(long *)&o_data[*(int *)&shape_child[i]];
       }
    }
// linkage check
    OBJ_TAINT(NArray);

    return(NArray);
}

VALUE
hdfeos5_ptreadlevel_float(VALUE mod)
{
    hid_t i_ptid;
    char *i_levelname;
    char *i_fieldname;
    int  i_level;
    int  i_ntype=10;
    int  i_nrecs;
    int  i_rank=1;

    int  i;
    int  *shape;    /* NArray uses int instead of size_t */
    int  *shape_child;    /* NArray uses int instead of size_t */
    char o_linkfield[HE5_BLKSIZE];
    float *o_data;
    float *o_data_new;
    herr_t status;
    VALUE NArray;

    HE5_CmpDTSinfo    dtsinfo;

    struct HE5PtField *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5PtField, he5point);
    i_levelname=he5point->levelname;
    i_fieldname=he5point->name;
    i_ptid=he5point->ptid;

    i_level=HE5_PTlevelindx(i_ptid, i_levelname);
    i_nrecs=HE5_PTnrecs(i_ptid, i_level);
    if(i_level <0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    status = HE5_PTlevelinfo(i_ptid, i_level, &dtsinfo); 
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    for(i=0;i<dtsinfo.nfields;i++) {
       if(strcmp(i_fieldname,dtsinfo.fieldname[i])==0){
          i_rank=dtsinfo.rank[i];
          i_ntype=dtsinfo.numtype[i];
       }
    }
    shape = ALLOCA_N(int,i_rank);
    for(i=0;i<i_rank;i++){
      shape[i_rank-1-i]=i_nrecs;
    }

    Cfloat_to_NArray(NArray,i_rank,shape,o_data);

    status = HE5_PTreadlevelF(i_ptid, i_level, i_fieldname, i_ntype, o_data);
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

// linkage check start
    status = HE5_PTfwdlinkinfo(i_ptid, i_level, o_linkfield);
    if( status !=FAIL ) {

       // parent level field 
       for(i=0;i<dtsinfo.nfields;i++) {
          if(strcmp(o_linkfield,dtsinfo.fieldname[i])==0){
             i_ntype=dtsinfo.numtype[i];
          }
       }
       // child level field 
       i_nrecs=HE5_PTnrecs(i_ptid, i_level+1);
       for(i=0;i<i_rank;i++){
         shape[i_rank-1-i]=i_nrecs;
       }
       Cfloat_to_NArray(NArray,i_rank,shape,o_data_new);
       shape_child=ALLOCA_N(int,i_nrecs);

       // set pointer
       switch (i_ntype){
       case  HE5T_NATIVE_INT8:
       case  HE5T_NATIVE_UINT8:
           sort_data_byte(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       case  HE5T_NATIVE_SHORT:
       case  HE5T_NATIVE_USHORT:
       case  HE5T_NATIVE_INT16:
       case  HE5T_NATIVE_UINT16:
           sort_data_short(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       case  HE5T_NATIVE_INT:
       case  HE5T_NATIVE_UINT:
       case  HE5T_NATIVE_INT32:
       case  HE5T_NATIVE_UINT32:
           sort_data_int(i_ptid, i_level, o_linkfield, shape_child);
 	   break;
       case  HE5T_NATIVE_LONG:
           sort_data_long(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       case  HE5T_NATIVE_FLOAT:
           sort_data_float(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       case  HE5T_NATIVE_DOUBLE:
           sort_data_double(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       default:
	   rb_raise(rb_eHE5Error, "Sorry, number type %d is yet to be supoorted [%s:%d]",
		 i_ntype,__FILE__,__LINE__);
       }
       for(i=0;i<i_nrecs;++i){
          *(float *)&o_data_new[i] = *(float *)&o_data[*(int *)&shape_child[i]];
       }
    }
// linkage check
    OBJ_TAINT(NArray);

    return(NArray);
}

VALUE
hdfeos5_ptreadlevel_double(VALUE mod)
{
    hid_t i_ptid;
    char *i_levelname;
    char *i_fieldname;
    int  i_level;
    int  i_nrecs;
    int  i_ntype=11;
    int  i_rank=1;

    int  i;
    int  *shape;    /* NArray uses int instead of size_t */
    int  *shape_child;    /* NArray uses int instead of size_t */
    char o_linkfield[HE5_BLKSIZE];
    double *o_data;
    double *o_data_new;
    herr_t status;
    VALUE NArray;

    HE5_CmpDTSinfo    dtsinfo;

    struct HE5PtField *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5PtField, he5point);
    i_levelname=he5point->levelname;
    i_fieldname=he5point->name;
    i_ptid=he5point->ptid;

    i_level=HE5_PTlevelindx(i_ptid, i_levelname);
    i_nrecs=HE5_PTnrecs(i_ptid, i_level);
    if(i_level <0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    status = HE5_PTlevelinfo(i_ptid, i_level, &dtsinfo); 
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    for(i=0;i<dtsinfo.nfields;i++) {
       if(strcmp(i_fieldname,dtsinfo.fieldname[i])==0){
          i_rank=dtsinfo.rank[i];
          i_ntype=dtsinfo.numtype[i];
       }
    }
    shape = ALLOCA_N(int,i_rank);
    for(i=0;i<i_rank;i++){
      shape[i_rank-1-i]=i_nrecs;
    }
    Cdouble_to_NArray(NArray,i_rank,shape,o_data);

    status = HE5_PTreadlevelF(i_ptid, i_level, i_fieldname, i_ntype, o_data);
    if(status == FAIL) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

// linkage check start
    status = HE5_PTfwdlinkinfo(i_ptid, i_level, o_linkfield);
    if( status !=FAIL ) {

       // parent level field 
       for(i=0;i<dtsinfo.nfields;i++) {
          if(strcmp(o_linkfield,dtsinfo.fieldname[i])==0){
             i_ntype=dtsinfo.numtype[i];
          }
       }
       // child level field 
       i_nrecs=HE5_PTnrecs(i_ptid, i_level+1);
       for(i=0;i<i_rank;i++){
         shape[i_rank-1-i]=i_nrecs;
       }
       Cdouble_to_NArray(NArray,i_rank,shape,o_data_new);
       shape_child=ALLOCA_N(int,i_nrecs);

       // set pointer
       switch (i_ntype){
       case  HE5T_NATIVE_INT8:
       case  HE5T_NATIVE_UINT8:
           sort_data_byte(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       case  HE5T_NATIVE_SHORT:
       case  HE5T_NATIVE_USHORT:
       case  HE5T_NATIVE_INT16:
       case  HE5T_NATIVE_UINT16:
           sort_data_short(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       case  HE5T_NATIVE_INT:
       case  HE5T_NATIVE_UINT:
       case  HE5T_NATIVE_INT32:
       case  HE5T_NATIVE_UINT32:
           sort_data_int(i_ptid, i_level, o_linkfield, shape_child);
 	   break;
       case  HE5T_NATIVE_LONG:
           sort_data_long(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       case  HE5T_NATIVE_FLOAT:
           sort_data_float(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       case  HE5T_NATIVE_DOUBLE:
           sort_data_double(i_ptid, i_level, o_linkfield, shape_child);
	   break;
       default:
	   rb_raise(rb_eHE5Error, "Sorry, number type %d is yet to be supoorted [%s:%d]",
		 i_ntype,__FILE__,__LINE__);
       }
       for(i=0;i<i_nrecs;++i){
          *(double *)&o_data_new[i] = *(double *)&o_data[*(int *)&shape_child[i]];
       }
    }
// linkage check end

    OBJ_TAINT(NArray);

    return(NArray);
}

VALUE
hdfeos5_ptupdatelevel_char(VALUE mod, VALUE nrec, VALUE recs, VALUE data)
{
    hid_t i_ptid;
    int  i_level;
    char *i_levelname;
    char *i_fieldname;
    long i_nrec;
    long *i_recs;

    int  len;
    int  *shape;    /* NArray uses int instead of size_t */
    int i_ntype;
    herr_t status;
    unsigned char *i_data;

    struct HE5PtField *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5PtField, he5point);
    i_levelname=he5point->levelname;
    i_fieldname=he5point->name;
    i_ptid=he5point->ptid;

    i_nrec = NUM2INT(nrec);
    i_recs = hdfeos5_obj2clongary(recs);

    i_level=HE5_PTlevelindx(i_ptid, i_levelname);
    if(i_level <0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    Array_to_Cbyte_len_shape(data,i_data,len,shape);
    i_ntype=check_numbertype("char");

    status = HE5_PTupdatelevelF(i_ptid, i_level, i_fieldname, i_nrec, i_recs, i_ntype, i_data);
    if(status < 0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    hdfeos5_freeclongary(i_recs);
    return status;
}

VALUE
hdfeos5_ptupdatelevel_short(VALUE mod, VALUE nrec, VALUE recs, VALUE data)
{
    hid_t i_ptid;
    int  i_level;
    char *i_levelname;
    char *i_fieldname;
    long i_nrec;
    long *i_recs;

    int  len;
    int  *shape;    /* NArray uses int instead of size_t */
    int i_ntype;
    herr_t status;
    short *i_data;

    struct HE5PtField *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5PtField, he5point);
    i_levelname=he5point->levelname;
    i_fieldname=he5point->name;
    i_ptid=he5point->ptid;

    i_nrec = NUM2INT(nrec);
    i_recs = hdfeos5_obj2clongary(recs);

    i_level=HE5_PTlevelindx(i_ptid, i_levelname);
    if(i_level <0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    Array_to_Cint_len_shape(data,i_data,len,shape);
    i_ntype=check_numbertype("short");

    status = HE5_PTupdatelevelF(i_ptid, i_level, i_fieldname, i_nrec, i_recs, i_ntype, i_data);
    if(status < 0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    hdfeos5_freeclongary(i_recs);
    return status;
}

VALUE
hdfeos5_ptupdatelevel_int(VALUE mod, VALUE nrec, VALUE recs, VALUE data)
{
    hid_t i_ptid;
    int  i_level;
    char *i_levelname;
    char *i_fieldname;
    long i_nrec;
    long *i_recs;

    int  len;
    int  *shape;    /* NArray uses int instead of size_t */
    int  i_ntype;
    herr_t status;
    int *i_data;

    struct HE5PtField *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5PtField, he5point);
    i_levelname=he5point->levelname;
    i_fieldname=he5point->name;
    i_ptid=he5point->ptid;

    i_nrec = NUM2INT(nrec);
    i_recs = hdfeos5_obj2clongary(recs);

    i_level=HE5_PTlevelindx(i_ptid, i_levelname);
    if(i_level <0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    Array_to_Clint_len_shape(data,i_data,len,shape);
    i_ntype=check_numbertype("int");

    status = HE5_PTupdatelevelF(i_ptid, i_level, i_fieldname, i_nrec, i_recs, i_ntype, i_data);
    if(status < 0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    hdfeos5_freeclongary(i_recs);
    return status;
}

VALUE
hdfeos5_ptupdatelevel_long(VALUE mod, VALUE nrec, VALUE recs, VALUE data)
{
    hid_t i_ptid;
    int  i_level;
    char *i_levelname;
    char *i_fieldname;
    long i_nrec;
    long *i_recs;

    int  len;
    int  *shape;    /* NArray uses int instead of size_t */
    int  i_ntype;
    herr_t status;
    long *i_data;

    struct HE5PtField *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5PtField, he5point);
    i_levelname=he5point->levelname;
    i_fieldname=he5point->name;
    i_ptid=he5point->ptid;

    i_nrec = NUM2INT(nrec);
    i_recs = hdfeos5_obj2clongary(recs);

    i_level=HE5_PTlevelindx(i_ptid, i_levelname);
    if(i_level <0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    Array_to_Clong_len_shape(data,i_data,len,shape);
    i_ntype=check_numbertype("long");

    status = HE5_PTupdatelevelF(i_ptid, i_level, i_fieldname, i_nrec, i_recs, i_ntype, i_data);
    if(status < 0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    hdfeos5_freeclongary(i_recs);
    return status;
}

VALUE
hdfeos5_ptupdatelevel_float(VALUE mod, VALUE nrec, VALUE recs, VALUE data)
{
    hid_t i_ptid;
    int  i_level;
    char *i_levelname;
    char *i_fieldname;
    long i_nrec;
    long *i_recs;

    int  len;
    int  *shape;    /* NArray uses int instead of size_t */
    int  i_ntype;
    herr_t status;
    float *i_data;

    struct HE5PtField *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5PtField, he5point);
    i_levelname=he5point->levelname;
    i_fieldname=he5point->name;
    i_ptid=he5point->ptid;

    i_nrec = NUM2INT(nrec);
    i_recs = hdfeos5_obj2clongary(recs);

    i_level=HE5_PTlevelindx(i_ptid, i_levelname);
    if(i_level <0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    Array_to_Cfloat_len_shape(data,i_data,len,shape);
    i_ntype=check_numbertype("sfloat");

    status = HE5_PTupdatelevelF(i_ptid, i_level, i_fieldname, i_nrec, i_recs, i_ntype, i_data);
    hdfeos5_freeclongary(i_recs);
    if(status < 0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    return status;
}

VALUE
hdfeos5_ptupdatelevel_double(VALUE mod, VALUE nrec, VALUE recs, VALUE data)
{
    hid_t i_ptid;
    int  i_level;
    char *i_levelname;
    char *i_fieldname;
    long i_nrec;
    long *i_recs;

    int  len;
    int  *shape;    /* NArray uses int instead of size_t */
    int  i_ntype;
    herr_t status;
    double *i_data;

    struct HE5PtField *he5point;
    rb_secure(4);
    Data_Get_Struct(mod, struct HE5PtField, he5point);
    i_levelname=he5point->levelname;
    i_fieldname=he5point->name;
    i_ptid=he5point->ptid;

    i_nrec = NUM2INT(nrec);
    i_recs = hdfeos5_obj2clongary(recs);

    i_level=HE5_PTlevelindx(i_ptid, i_levelname);
    if(i_level <0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);

    Array_to_Cdouble_len_shape(data,i_data,len,shape);
    i_ntype=check_numbertype("float");

    status = HE5_PTupdatelevelF(i_ptid, i_level, i_fieldname, i_nrec, i_recs, i_ntype, i_data);
    if(status < 0) rb_raise(rb_eHE5Error, "ERROR [%s:%d]",__FILE__,__LINE__);
    hdfeos5_freeclongary(i_recs);
    return status;
}

void
init_hdfeos5pt_wrap(void)
{
    mNumRu = rb_define_module("NumRu");

    /* Difinitions of the classes */;
    cHE5 = rb_define_class_under(mNumRu, "HE5",rb_cObject);
    cHE5Pt = rb_define_class_under(mNumRu, "HE5Pt",rb_cObject);
    cHE5PtField = rb_define_class_under(mNumRu, "HE5PtField",rb_cObject);
    rb_eHE5Error = rb_define_class("HE5Error",rb_eStandardError);

    /* Class Constants Definition */
    /* Difinitions of the HE5 Class */;
    rb_define_method(cHE5, "ptcreate", hdfeos5_ptcreate, 1);
    rb_define_method(cHE5, "ptattach", hdfeos5_ptattach, 1);
    rb_define_method(cHE5, "inqpoint", hdfeos5_ptinqpoint, 0);
    rb_define_method(cHE5, "chkpoint", hdfeos5_ptchkpoint, 0);
    rb_define_method(cHE5, "chkpointname", hdfeos5_ptchkpointname, 0);
    /* Difinitions of the HE5 Point Class */
    rb_define_method(cHE5Pt, "ptdetach", hdfeos5_ptdetach, 0);
    rb_define_method(cHE5Pt, "nrecs", hdfeos5_ptnrecs, 1);
    rb_define_method(cHE5Pt, "nlevels", hdfeos5_ptnlevels, 0);
    rb_define_method(cHE5Pt, "nfields", hdfeos5_ptnfields, 0);
    rb_define_method(cHE5Pt, "getlevelname", hdfeos5_ptgetlevelname, 0);
    rb_define_method(cHE5Pt, "deflevel", hdfeos5_ptdeflevel, 6);
    rb_define_method(cHE5Pt, "deflinkage", hdfeos5_ptdeflinkage, 3);
    rb_define_method(cHE5Pt, "writeattr", hdfeos5_ptwriteattr, 4);
    rb_define_method(cHE5Pt, "get_att_", hdfeos5_pt_get_att, 1);
    rb_define_method(cHE5Pt, "inqdatatype", hdfeos5_ptinqdatatype, 3);
    rb_define_method(cHE5Pt, "inqattrs", hdfeos5_ptinqattrs, 0);
    rb_define_method(cHE5Pt, "writegrpattr", hdfeos5_ptwritegrpattr, 4);
    rb_define_method(cHE5Pt, "get_grpatt_", hdfeos5_pt_get_grpatt, 1);
    rb_define_method(cHE5Pt, "inqgrpattrs", hdfeos5_ptinqgrpattrs, 0);
    /* Original of the HE5 Point Class */;
    rb_define_method(cHE5Pt, "file", hdfeos5_pt_file, 0);
    rb_define_method(cHE5Pt, "name", hdfeos5_pt_inqname, 0);
    rb_define_method(cHE5Pt, "define_mode?", hdfeos5_pt_whether_in_define_mode, 0);
    rb_define_method(cHE5Pt, "setfield", hdfeos5_ptsetfield, 1);
    rb_define_method(cHE5Pt, "setfield_level", hdfeos5_ptsetfield_level, 2);
    rb_define_method(cHE5Pt, "chkfield", hdfeos5_ptchkfieldname, 1);

    /* Difinitions of the HE5 Point level Class */;
    rb_define_method(cHE5PtField, "writelevel", hdfeos5_ptwritelevel, 3);
    rb_define_method(cHE5PtField, "fieldinfo", hdfeos5_ptfieldinfo, 0);
    rb_define_method(cHE5PtField, "readlevel", hdfeos5_ptreadlevel, 1);
    rb_define_method(cHE5PtField, "writelocattr", hdfeos5_ptwritelocattr, 4);
    rb_define_method(cHE5PtField, "get_att_", hdfeos5_ptfield_get_att, 1);
    rb_define_method(cHE5PtField, "inqlocattrs", hdfeos5_ptinqlocattrs, 0);
    rb_define_method(cHE5PtField, "levelindx", hdfeos5_ptlevelindx, 0);
    rb_define_method(cHE5PtField, "updatelevel", hdfeos5_ptupdatelevel, 4);

    rb_define_method(cHE5PtField, "put_vars_char", hdfeos5_ptwritelevel_char, 2);
    rb_define_method(cHE5PtField, "put_vars_int", hdfeos5_ptwritelevel_int, 2);
    rb_define_method(cHE5PtField, "put_vars_long", hdfeos5_ptwritelevel_long, 2);
    rb_define_method(cHE5PtField, "put_vars_float", hdfeos5_ptwritelevel_float, 2);
    rb_define_method(cHE5PtField, "put_vars_double", hdfeos5_ptwritelevel_double, 2);
    rb_define_method(cHE5PtField, "put_vars_short", hdfeos5_ptwritelevel_short, 2);
    
    rb_define_method(cHE5PtField, "get_vars_char", hdfeos5_ptreadlevel_char, 0);
    rb_define_method(cHE5PtField, "get_vars_int", hdfeos5_ptreadlevel_int, 0);
    rb_define_method(cHE5PtField, "get_vars_long", hdfeos5_ptreadlevel_long, 0);
    rb_define_method(cHE5PtField, "get_vars_float", hdfeos5_ptreadlevel_float, 0);
    rb_define_method(cHE5PtField, "get_vars_double", hdfeos5_ptreadlevel_double, 0);
    rb_define_method(cHE5PtField, "get_vars_short", hdfeos5_ptreadlevel_short, 0);

    /* Original of the HE5 Point level Class */;
    rb_define_method(cHE5PtField, "point", hdfeos5_level_point, 0);
    rb_define_method(cHE5PtField, "name", hdfeos5_level_inqname, 0);
    rb_define_method(cHE5PtField, "getfield", hdfeos5_ptgetfield, 0);
    rb_define_method(cHE5PtField, "fwdlink", hdfeos5_ptfwdlinkinfo, 0);
    rb_define_method(cHE5PtField, "bcklink", hdfeos5_ptbcklinkinfo, 0);
}

