From 1b8ff660c281f6ba7a5f9ff0b80e48fed8dd18f1 Mon Sep 17 00:00:00 2001 From: Guilhem Lavaux Date: Tue, 2 Dec 2008 11:00:28 -0600 Subject: [PATCH] Initial commit --- .gitignore | 3 + config.hpp | 97 ++++++++++++ loadRamses.cpp | 390 +++++++++++++++++++++++++++++++++++++++++++++++++ loadRamses.hpp | 13 ++ load_data.h | 84 +++++++++++ yorick.cpp | 298 +++++++++++++++++++++++++++++++++++++ yorick.hpp | 211 ++++++++++++++++++++++++++ 7 files changed, 1096 insertions(+) create mode 100644 .gitignore create mode 100644 config.hpp create mode 100644 loadRamses.cpp create mode 100644 loadRamses.hpp create mode 100644 load_data.h create mode 100644 yorick.cpp create mode 100644 yorick.hpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c248456 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*~ +*.o +*.prog diff --git a/config.hpp b/config.hpp new file mode 100644 index 0000000..4674a94 --- /dev/null +++ b/config.hpp @@ -0,0 +1,97 @@ +#ifndef __MAK_CONFIG_HPP +#define __MAK_CONFIG_HPP + +#include +#include +#include + +namespace CosmoTool +{ + +#define NUMDIMS 3 +#define NUMCUBES 8 + + /** + * Base type to specity at what precision we + * must achieve computations. + */ + typedef double ComputePrecision; + /** + * Coordinate type (should be a 3-array). + */ + typedef double Coordinates[NUMDIMS]; + + /** + * This function is used whenever one needs a general + * conversion between mass and luminosity (or the opposite). + * It should take a "mass" (or luminosity) in input, a unit is + * given to convert this mass into solar units. The output should + * be the "luminosity" (or mass), in solar units. + */ + typedef double (*BiasFunction)(double mass, double unit); + + /** + * Function to copy the coordinates "a" into "b". + */ + inline void copyCoordinates(const Coordinates& a, Coordinates& b) + { + memcpy(b, a, sizeof(a)); + } + + /** + * Base exception class for all exceptions handled by + * this library. + */ + class Exception : public std::exception + { + public: + Exception(const char *mess = 0) + : msg(mess) {} + + const char *getMessage() const { return msg; }; + virtual const char *what() const throw () { return msg; }; + + private: + const char *msg; + }; + + /** + * Exception raised when an invalid argument has been + * passed to a function of the library. + */ + class InvalidArgumentException : public Exception + { + public: + InvalidArgumentException(const char *mess = 0) + : Exception(mess) {} + }; + + /** + */ + class InvalidRangeException : public Exception + { + public: + InvalidRangeException(const char *mess = 0) + : Exception(mess) {} + }; + + /** + */ + class NoSuchFileException : public Exception + { + public: + NoSuchFileException(const char *mess = 0) + : Exception(mess) {} + }; + + /** + */ + class InvalidFileFormatException : public Exception + { + public: + InvalidFileFormatException(const char *mess = 0) + : Exception(mess) {} + }; +}; + +#endif diff --git a/loadRamses.cpp b/loadRamses.cpp new file mode 100644 index 0000000..5aad5a4 --- /dev/null +++ b/loadRamses.cpp @@ -0,0 +1,390 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "loadRamses.hpp" +#include "load_data.h" + +using namespace std; + +#if 0 +#define read_buf(b, n) \ +{ \ + int k; \ + control_size -= n; \ + for (k = (n-1); k >= 0; k--) \ + infile.read(&b[k],1); \ +} +#else +#define read_buf(b, n) \ +{ \ + int k; \ + control_size -= n; \ + for (k = 0; k < n; k++) \ + infile.read(&b[k], 1); \ +} +#endif + +#define read_int(i) \ +{ \ + char *o = (char*)&(i); \ + read_buf(o, 4); \ +} + +#define read_real(f) \ +{ \ + char *o = (char*)&(f); \ + read_buf(o, 4); \ +} + +#define read_characters(c, n) { \ + int k; \ + control_size -= n; \ + infile.read(c, n); \ +} + +#define push_dummy_control(id) \ +{ int control_size = 0; + +#define pop_dummy_control() } + +#define push_control(id) \ +{ \ + int control_size = 0; \ + int control_size2 = 0; \ + char *intbuf = (char*)&control_size; \ + read_int(control_size); + +#define pop_control(id) \ + assert(control_size == 0); \ + read_int(control_size2); \ +} + +GadgetData *CosmoTool::loadRamses(const char *name) +{ + GadgetData *gd = (GadgetData *)malloc(sizeof(GadgetData)); + int id = 1; + uint32_t totPart = 0; + + cout << "Detecting number of files and particles..." << endl; + while (1) + { + ostringstream ss_fname; + ss_fname << name << setfill('0') << setw(5) << id; + string fname = ss_fname.str(); + + cout << " ... " << fname << endl; + + ifstream infile(fname.c_str()); + if (!infile) + break; + + int nCpu, ndim, nPar; + + push_control(CPU); + read_int(nCpu); + pop_control(CPU); + + push_control(DIM); + read_int(ndim); + pop_control(DIM); + + push_control(NPAR); + read_int(nPar); + pop_control(NPAR); + + cout << " NUMCPU=" << nCpu << " NUMDIM=" << ndim << " NumPart=" << nPar << endl; + + totPart += nPar; + id++; + } + + assert (totPart <= ((~(size_t)0)/sizeof(ParticleState))); + size_t memSize = sizeof(ParticleState)*(size_t)totPart; + cout << " Needing " << memSize / 1024 << " kBytes" << endl; + gd->particles = (ParticleState *)malloc(memSize); + assert(gd->particles != 0); + gd->NumPart = totPart; + gd->ntot_withmasses = totPart; + gd->header.npart[0] = totPart; + for (int k = 1; k < 6; k++) + { + gd->header.npart[k] = 0; + gd->header.mass[k] = 0; + } + gd->header.num_files = id; + gd->header.BoxSize = 200.0 * 1000; // kPc + gd->header.Omega0 = 0.30; // ???? + gd->header.OmegaLambda = 0.70; // ???? + gd->header.HubbleParam = 0.70; // ???? + + cout << " Total number part=" << totPart << endl + << "Loading particles ..." << endl; + + uint32_t curPos = 0; + id = 1; + while (1) + { + ostringstream ss_fname; + ss_fname << name << setfill('0') << setw(5) << id; + string fname = ss_fname.str(); + + cout << " ... " << id; + cout.flush(); + + ifstream infile(fname.c_str()); + if (!infile) + break; + + int nCpu, ndim, nPar; + + push_control(CPU); + read_int(nCpu); + pop_control(CPU); + + push_control(DIM); + read_int(ndim); + pop_control(DIM); + + push_control(NPAR); + read_int(nPar); + pop_control(NPAR); + + ParticleState *s = &gd->particles[curPos]; + + for (uint32_t i = nPar; i > 0; i--,s++) + s->Mass = 1.0; + + s = &gd->particles[curPos]; + push_control(POSX); + for (uint32_t i = nPar; i > 0; i--) + { + read_real(s->Pos[0]); + s->Pos[0] *= gd->header.BoxSize; + s++; + } + pop_control(POSX); + + s = &gd->particles[curPos]; + push_control(POSY); + for (uint32_t i = nPar; i > 0; i--) + { + read_real(s->Pos[1]); + s->Pos[1] *= gd->header.BoxSize; + s++; + } + pop_control(POSY); + + s = &gd->particles[curPos]; + push_control(POSZ); + for (uint32_t i = nPar; i > 0; i--) + { + read_real(s->Pos[2]); + s->Pos[2] *= gd->header.BoxSize; + s++; + } + pop_control(POSZ); + + push_control(VELX); + for (uint32_t i = 0; i < nPar; i++) + { + read_real(gd->particles[curPos+i].Vel[0]); + } + pop_control(VELX); + + push_control(VELY); + for (uint32_t i = 0; i < nPar; i++) + { + read_real(gd->particles[curPos+i].Vel[1]); + } + pop_control(VELY); + + push_control(VELZ); + for (uint32_t i = 0; i < nPar; i++) + { + read_real(gd->particles[curPos+i].Vel[2]); + } + pop_control(VELZ); + + curPos += nPar; + + id++; + } + + cout << endl; + + return gd; +} + +PurePositionData *CosmoTool::loadRamsesPosition(const char *name) +{ + PurePositionData *gd = (PurePositionData *)malloc(sizeof(PurePositionData)); + int id = 1; + uint32_t totPart = 0; + int nCpu = 0; + + cout << "Detecting number of files and particles..." << endl; + while (1) + { + ostringstream ss_fname; + ss_fname << name << setfill('0') << setw(5) << id; + string fname = ss_fname.str(); + + cout << " ... " << fname << endl; + + ifstream infile(fname.c_str()); + if (!infile) + break; + + int ndim, nPar; + + push_control(CPU); + read_int(nCpu); + pop_control(CPU); + + push_control(DIM); + read_int(ndim); + pop_control(DIM); + + push_control(NPAR); + read_int(nPar); + pop_control(NPAR); + + cout << " NUMCPU=" << nCpu << " NUMDIM=" << ndim << " NumPart=" << nPar << endl; + + totPart += nPar; + id++; + } + + assert (totPart <= ((~(size_t)0)/sizeof(FCoordinates))); + size_t memSize = sizeof(FCoordinates)*(size_t)(totPart+totPart/nCpu); + cout << " Needing " << memSize / 1024 << " kBytes" << endl; + gd->pos = (FCoordinates *)malloc(sizeof(FCoordinates)*totPart); + assert(gd->pos != 0); + gd->NumPart = totPart; + gd->BoxSize = 1000.0; + + cout << " Total number part=" << totPart << endl + << "Loading particles ..." << endl; + + uint32_t curPos = 0; + id = 1; + while (1) + { + ostringstream ss_fname; + ss_fname << name << setfill('0') << setw(5) << id; + string fname = ss_fname.str(); + int *idP; + + cout << " ... " << id; + cout.flush(); + + ifstream infile(fname.c_str()); + if (!infile) + break; + + int nCpu, ndim, nPar; + + push_control(CPU); + read_int(nCpu); + pop_control(CPU); + + push_control(DIM); + read_int(ndim); + pop_control(DIM); + + push_control(NPAR); + read_int(nPar); + pop_control(NPAR); + + FCoordinates *s = new FCoordinates[nPar]; + + push_control(POSX); + for (uint32_t i = 0; i < nPar; i++) + { + read_real(s[i][0]); + s[i][0] *= gd->BoxSize; + } + pop_control(POSX); + + push_control(POSY); + for (uint32_t i = 0; i < nPar; i++) + { + read_real(s[i][1]); + s[i][1] *= gd->BoxSize; + } + pop_control(POSY); + + push_control(POSZ); + for (uint32_t i = 0; i < nPar; i++) + { + read_real(s[i][2]); + s[i][2] *= gd->BoxSize; + } + pop_control(POSZ); + + // SKIP VELOCITIES + for (int k = 0; k < 3; k++) { + push_control(V); + for (uint32_t i = nPar; i > 0; i--) + { + float dummyF; + read_real(dummyF); + } + pop_control(V); + } + + float minMass = INFINITY; + push_control(MASS); + for (uint32_t i = nPar; i > 0; i--) + { + float dummyF; + read_real(dummyF); + if (dummyF < minMass) minMass = dummyF; + } + pop_control(MASS); + + push_control(ID); + for (uint32_t i = 0; i < nPar; i++) + { + int id; + read_int(id); + id--; + assert(id >= 0); + assert(id < totPart); + memcpy(&gd->pos[id], &s[i], sizeof(FCoordinates)); + } + pop_control(ID); + + delete[] s; + + curPos += nPar; + + id++; + } + + cout << endl; + + return gd; +} + +#if 0 +int main(int argc, char **argv) +{ + GadgetData *gd = loadRamses(argv[1]); +} + +#endif + +#if 0 +int main(int argc, char **argv) +{ + GadgetData *gd = loadRamses(argv[1]); +} + +#endif diff --git a/loadRamses.hpp b/loadRamses.hpp new file mode 100644 index 0000000..e831317 --- /dev/null +++ b/loadRamses.hpp @@ -0,0 +1,13 @@ +#ifndef _LOAD_RAMSES_HPP +#define _LOAD_RAMSES_HPP + +#include "load_data.h" + +namespace CosmoTool { + +GadgetData *loadRamses(const char *name); +PurePositionData *loadRamsesPosition(const char *fname); + +}; + +#endif diff --git a/load_data.h b/load_data.h new file mode 100644 index 0000000..e89b00d --- /dev/null +++ b/load_data.h @@ -0,0 +1,84 @@ +#ifndef _LOAD_GADGET_DATA_H +#define _LOAD_GADGET_DATA_H + + +typedef struct io_header_1 +{ + int npart[6]; + double mass[6]; + double time; + double redshift; + int flag_sfr; + int flag_feedback; + int npartTotal[6]; + int flag_cooling; + int num_files; + double BoxSize; + double Omega0; + double OmegaLambda; + double HubbleParam; + char fill[256- 6*4- 6*8- 2*8- 2*4- 6*4- 2*4 - 4*8]; /* fills to 256 Bytes */ +} GadgetHeader; + +typedef struct particle_data +{ + float Pos[3]; + float Init[3]; + float Vel[3]; + float VelInit[3]; + float Mass; + int Type; + + float Rho, U, Temp, Ne; + int Id; +} ParticleState; + +typedef struct { + GadgetHeader header; + ParticleState *particles; + int NumPart; + int ntot_withmasses; +} GadgetData; + +typedef struct { + int Ntypes; + float BoxSize; + float RedShift; + char header[256 - 4 - 2*4]; +} ParticleSetHeader; + +typedef struct { + ParticleSetHeader header; + // Particle description + int *Npart; + ParticleState **particles; +} ParticleSet; + +typedef float FCoordinates[3]; + +typedef struct { + unsigned int NumPart; + double BoxSize; + FCoordinates *pos; +} PurePositionData; + +#ifdef __cplusplus +extern "C" { +#endif + + void writeGadget(GadgetData *data, const char *fname); + GadgetData *loadGadget(const char *fname); + void freeGadget(GadgetData *data); + + GadgetData *loadSimulationData(const char *fname); + GadgetData *loadHydra(const char *fname); + + void writePersoSet(ParticleSet *set, const char *fname); + ParticleSet *loadPersoSet(const char *fname); + void freePersoSet(ParticleSet *set); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/yorick.cpp b/yorick.cpp new file mode 100644 index 0000000..00fcdfc --- /dev/null +++ b/yorick.cpp @@ -0,0 +1,298 @@ +#include "config.hpp" +#include +#include +#include "yorick.hpp" +#include + +using namespace CosmoTool; +using namespace std; + +OutputNetCDF::OutputNetCDF(NcFile *f, NcVar *v, long *dimList, uint32_t rank) +{ + this->outFile = f; + this->curVar = v; + this->dimList = dimList; + this->rank = rank; + this->counts = new long[rank]; + this->curPos = new long[rank]; + + for (long i = 0; i < rank; i++) + this->curPos[i] = 0; + + for (long i = 0; i < rank; i++) + this->counts[i] = 1; +} + +void OutputNetCDF::addDouble(double a) +{ + curVar->set_cur(curPos); + curVar->put(&a, counts); + + curPos[rank-1]++; + for (long i = rank-1; i >= 1; i--) + { + if (curPos[i] == dimList[i]) + { + curPos[i-1]++; + curPos[i] = 0; + } + } +} + +OutputNetCDF::~OutputNetCDF() +{ + delete counts; + delete dimList; + delete curPos; + delete outFile; +} + +class NetCDF_handle +{ +public: + NcFile *outFile; + NcVar *curVar; + long *curPos; + long *counts; + long *dimList; + uint32_t rank; + + NetCDF_handle(NcFile *f, NcVar *v, long *dimList, uint32_t rank); + virtual ~NetCDF_handle(); +}; + +NetCDF_handle::NetCDF_handle(NcFile *f, NcVar *v, long *dimList, uint32_t rank) +{ + this->outFile = f; + this->curVar = v; + this->dimList = dimList; + this->rank = rank; + this->counts = new long[rank]; + this->curPos = new long[rank]; + + for (long i = 0; i < rank; i++) + this->curPos[i] = 0; + + for (long i = 0; i < rank; i++) + this->counts[i] = 1; +} + +NetCDF_handle::~NetCDF_handle() +{ + delete[] dimList; + delete outFile; +} + +template +class InputGenCDF: public NetCDF_handle, public ProgressiveInputImpl +{ +public: + InputGenCDF(NcFile *f, NcVar *v, long *dimList, uint32_t rank) + : NetCDF_handle(f,v,dimList,rank) + {} + virtual ~InputGenCDF() {} + + virtual T read() + { + T a; + + curVar->set_cur(curPos); + curVar->get(&a, counts); + + curPos[rank-1]++; + for (long i = rank-1; i >= 1; i--) + { + if (curPos[i] == dimList[i]) + { + curPos[i-1]++; + curPos[i] = 0; + } + } + return a; + } + + virtual void seek(uint32_t *pos) + { + for (long i = rank-1; i >= 0; i--) + curPos[i] = pos[rank-1-i]; + } +}; + +template +class OutputGenCDF: public NetCDF_handle, public ProgressiveOutputImpl +{ +public: + OutputGenCDF(NcFile *f, NcVar *v, long *dimList, uint32_t rank) + : NetCDF_handle(f,v,dimList,rank) + {} + virtual ~OutputGenCDF() {} + + virtual void put(T a) + { + curVar->set_cur(curPos); + curVar->put(&a, counts); + + curPos[rank-1]++; + for (long i = rank-1; i >= 1; i--) + { + if (curPos[i] == dimList[i]) + { + curPos[i-1]++; + curPos[i] = 0; + } + } + } +}; + +template +class NetCDF_type +{ +public: + static const NcType t = (NcType)-1; +}; + +template<> +class NetCDF_type +{ +public: + static const NcType t = ncInt; +}; + +template<> +class NetCDF_type +{ +public: + static const NcType t = ncFloat; +}; + +template<> +class NetCDF_type +{ +public: + static const NcType t = ncDouble; +}; + +namespace CosmoTool { + template + ProgressiveOutput + ProgressiveOutput::saveArrayProgressive(const char *fname, uint32_t *dimList, + uint32_t rank) + { + NcFile *f = new NcFile(fname, NcFile::Replace); + + assert(f->is_valid()); + + const NcDim **dimArray = new const NcDim *[rank]; + for (uint32_t i = 0; i < rank; i++) + { + char dimName[255]; + + sprintf(dimName, "dim%d", i); + dimArray[i] = f->add_dim(dimName, dimList[rank-1-i]); + } + + NcVar *v = f->add_var("array", NetCDF_type::t, rank, dimArray); + + long *ldimList = new long[rank]; + + for (uint32_t i = 0; i < rank; i++) + ldimList[rank-1-i] = dimList[i]; + + OutputGenCDF *impl = new OutputGenCDF(f, v, ldimList, rank); + return ProgressiveOutput(impl); + } + + template + ProgressiveInput + ProgressiveInput::loadArrayProgressive(const char *fname, uint32_t *&dimList, + uint32_t& rank) + { + NcFile *f = new NcFile(fname, NcFile::ReadOnly); + + assert(f->is_valid()); + + NcVar *v = f->get_var("array"); + + rank = v->num_dims(); + long *ldimList = v->edges(); + dimList = new uint32_t[rank]; + for (uint32_t i = 0; i < rank; i++) + { + dimList[rank-i-1] = ldimList[i]; + } + InputGenCDF *impl = new InputGenCDF(f, v, ldimList, rank); + + return ProgressiveInput(impl); + } + + template + void saveArray(const char *fname, + T *array, uint32_t *dimList, uint32_t rank) + { + NcFile f(fname, NcFile::Replace); + + assert(f.is_valid()); + + const NcDim **dimArray = new const NcDim *[rank]; + for (uint32_t i = 0; i < rank; i++) + { + char dimName[255]; + + sprintf(dimName, "dim%d", i); + dimArray[i] = f.add_dim(dimName, dimList[i]); + } + + NcVar *v = f.add_var("array", NetCDF_type::t, rank, dimArray); + + long *edge = v->edges(); + v->put(array, edge); + delete[] edge; + } + + template + void loadArray(const char *fname, + T*&array, uint32_t *&dimList, uint32_t& rank) + { + NcFile f(fname, NcFile::ReadOnly); + + if (!f.is_valid()) + throw NoSuchFileException(fname); + + NcVar *v = f.get_var("array"); + rank = v->num_dims(); + long *edge = v->edges(); + uint32_t fullSize = 1; + dimList = new uint32_t[rank]; + for (int i = 0; i < rank; i++) + { + dimList[i] = edge[i]; + fullSize *= edge[i]; + } + array = new T[fullSize]; + v->get(array, edge); + delete[] edge; + } + + template class ProgressiveInput; + template class ProgressiveInput; + template class ProgressiveInput; + + template class ProgressiveOutput; + template class ProgressiveOutput; + template class ProgressiveOutput; + + template void loadArray(const char *fname, + int*& array, uint32_t *&dimList, uint32_t& rank); + template void loadArray(const char *fname, + float*& array, uint32_t *&dimList, uint32_t& rank); + template void loadArray(const char *fname, + double*& array, uint32_t *&dimList, uint32_t& rank); + + template void saveArray(const char *fname, + int *array, uint32_t *dimList, uint32_t rank); + template void saveArray(const char *fname, + float *array, uint32_t *dimList, uint32_t rank); + template void saveArray(const char *fname, + double *array, uint32_t *dimList, uint32_t rank); + +} diff --git a/yorick.hpp b/yorick.hpp new file mode 100644 index 0000000..480c186 --- /dev/null +++ b/yorick.hpp @@ -0,0 +1,211 @@ +#ifndef __YORICK_HELPERS_HPP +#define __YORICK_HELPERS_HPP + +#include "config.hpp" +#include +#include + + +namespace CosmoTool +{ + + class ProgressiveDoubleOutputImpl + { + public: + virtual ~ProgressiveDoubleOutputImpl(); + virtual void addDouble(double d) = 0; + }; + + template + class ProgressiveInputImpl + { + public: + virtual ~ProgressiveInputImpl() {} + virtual T read() = 0; + virtual void seek(uint32_t *pos) = 0; + }; + + template + class ProgressiveOutputImpl + { + public: + virtual ~ProgressiveOutputImpl() {} + virtual void put(T a) = 0; + }; + + class ProgressiveDoubleOutput + { + private: + bool initialized; + int *ref; + ProgressiveDoubleOutputImpl *impl; + + friend ProgressiveDoubleOutput saveDoubleArrayProgressive(const char *fname, uint32_t *dimList, uint32_t rank); + void decRef(); + public: + ProgressiveDoubleOutput(); + ProgressiveDoubleOutput(ProgressiveDoubleOutputImpl *i); + ProgressiveDoubleOutput(const ProgressiveDoubleOutput& o); + ~ProgressiveDoubleOutput(); + + virtual void addDouble(double a); + + const ProgressiveDoubleOutput& operator=(const ProgressiveDoubleOutput& b); + }; + + template + class ProgressiveInput + { + private: + int *ref; + ProgressiveInputImpl *impl; + + void decRef() + { + if (ref == 0) + return; + + (*ref)--; + if (*ref == 0) + { + delete ref; + delete impl; + } + impl = 0; + ref = 0; + } + + public: + static ProgressiveInput + loadArrayProgressive(const char *fname, uint32_t *&dimList, + uint32_t& rank); + + ProgressiveInput() { + impl = 0; + ref = 0; + } + ProgressiveInput(ProgressiveInputImpl *i) { + impl = i; + ref = new int; + *ref = 1; + } + ProgressiveInput(const ProgressiveInput& o) { + ref = o.ref; + impl = o.impl; + (*ref)++; + } + ~ProgressiveInput() { + decRef(); + } + + T read() + { + return impl->read(); + } + + void seek(uint32_t *pos) + { + impl->seek(pos); + } + + const ProgressiveInput& operator=(const ProgressiveInput& b) + { + decRef(); + ref = b.ref; + impl = b.impl; + if (ref != 0) + (*ref)++; + return *this; + } + }; + + template + class ProgressiveOutput + { + private: + int *ref; + ProgressiveOutputImpl *impl; + + void decRef() + { + if (ref == 0) + return; + + (*ref)--; + if (*ref == 0) + { + delete ref; + delete impl; + } + impl = 0; + ref = 0; + } + + public: + static ProgressiveOutput + saveArrayProgressive(const char *fname, uint32_t *dimList, + uint32_t rank); + + ProgressiveOutput() { + impl = 0; + ref = 0; + } + ProgressiveOutput(ProgressiveOutputImpl *i) { + impl = i; + ref = new int; + *ref = 1; + } + ProgressiveOutput(const ProgressiveOutput& o) { + ref = o.ref; + impl = o.impl; + (*ref)++; + } + ~ProgressiveOutput() { + decRef(); + } + + void put(T a) + { + impl->put(a); + } + + const ProgressiveOutput& operator=(const ProgressiveOutput& b) + { + decRef(); + ref = b.ref; + impl = b.impl; + if (ref != 0) + (*ref)++; + return *this; + } + }; + + template + void saveArray(const char *fname, + T *array, uint32_t *dimList, uint32_t rank); + template + void loadArray(const char *fname, + T*& array, uint32_t *& dimList, uint32_t& rank); + + void saveFloatArray(const char *fname, + float *array, uint32_t *dimList, uint32_t rank); + void loadFloatArray(const char *fname, + float *&array, uint32_t *&dimList, uint32_t& rank) + throw (NoSuchFileException); + + void saveDoubleArray(const char *fname, + double *array, uint32_t *dimList, uint32_t rank); + void loadDoubleArray(const char *fname, + double *&array, uint32_t *&dimList, uint32_t& rank) + throw (NoSuchFileException); + + void loadIntArray(const char *fname, + int *&array, uint32_t *&dimList, uint32_t& rank) + throw (NoSuchFileException); + void saveIntArray(const char *fname, + int *array, uint32_t *dimList, uint32_t rank); + + ProgressiveDoubleOutput saveDoubleArrayProgressive(const char *fname, uint32_t *dimList, uint32_t rank); +}; + +#endif