#ifndef __AMSCPPNARRAY_BINRWIMPL_HPP__
#define __AMSCPPNARRAY_BINRWIMPL_HPP__



namespace ams
{
namespace narray
{

//binary array read/write operations

template<typename T> int fwrite_ndarray(FILE *fp, narray<T> *data, narray<int32_t> *shape)
{
    int ret = narray_success;
    narray_size_t piprod;
    narray_size_t I;
    int32_t Nd;
    narray<int32_t> *lshape=NULL;

    if(fp==NULL)
    {
        ret = narray_failure;
        printf("fwrite_ndarray: fp=NULL\n");
        return ret;
    }

    if(shape==NULL)
    {
        lshape = new(std::nothrow) narray<int32_t>();
        lshape->resize(1);
        lshape->data[0] = data->length;
    }
    else
    {
        lshape = shape;
    }

    piprod = 1;
    for(I=0;I<lshape->length;I++)
    {
        if(lshape->data[I]>0)
        {
            piprod = piprod*lshape->data[I];
        }
        else
        {
            piprod = 0; break;
        }
    }

    if(piprod!=data->length)
    {
        ret = narray_failure;
        printf("fwrite_ndarray: buffer is size %ld, while shape is size %ld\n",(long) data->length,(long) piprod);
        return ret;
    }

    Nd = lshape->length;

    fwrite(&Nd,sizeof(int32_t),1,fp);
    if(Nd>0)
    {
        fwrite(lshape->data,sizeof(int32_t),Nd,fp);
        if(piprod>0)
        {
            fwrite(data->data,sizeof(T),data->length,fp);
        }
    }

    if(shape==NULL)
    {
        if(lshape!=NULL) {delete lshape; lshape=NULL;}
    }
    

    return ret;
}

template<typename T> int fread_ndarray(FILE *fp, narray<T> *data, narray<int32_t> *shape)
{
    int ret = narray_success;
    narray_size_t piprod;
    narray_size_t I;
    int32_t Nd;
    narray<int32_t> *lshape=NULL;

    if(fp==NULL)
    {
        ret = narray_failure;
        printf("fread_ndarray: fp=NULL\n");
        return ret;
    }

    if(shape==NULL)
    {
        lshape = new(std::nothrow) narray<int32_t>();
    }
    else
    {
        lshape = shape;
    }



    fread(&Nd,sizeof(int32_t),1,fp);
    if(Nd<=0)
    {
        data->resize(0);
        lshape->resize(0);
        ret = narray_failure;
        return ret;
    }
    lshape->resize(Nd);
    fread(lshape->data,sizeof(int32_t),Nd,fp);

    piprod = 1;
    for(I=0;I<lshape->length;I++)
    {
        if(lshape->data[I]>0)
        {
            piprod = piprod*lshape->data[I];
        }
        else
        {
            piprod = 0; break;
        }
    }

    if(piprod<=0)
    {
        data->resize(0);
        lshape->resize(0);
        ret = narray_failure;
        return ret;
    }

    data->resize(piprod);
    fread(data->data,sizeof(T),data->length,fp);

    if(shape==NULL)
    {
        if(lshape!=NULL) {delete lshape; lshape=NULL;}
    }
    
    return ret;
}


};
};

#endif