#ifndef PART_H
#define PART_H 1

/* $Id: part.h,v 1.5 2006/11/16 14:59:34 knolli Exp $ */

/**
 * \file part.h
 *
 * Provides particle structure and functions working on them.
 */


/***********************************************************************\
 *    Includes                                                         * 
\***********************************************************************/
#include <stdint.h>
#include <io_logging.h>


/***********************************************************************\
 *    Global defines, structure definitions and typedefs               * 
\***********************************************************************/

/** The type for the particle ID */
typedef int32_t part_id_t;

/** Convenient typedef */
typedef struct dpart_struct dpart_struct_t;

/** Convenient typedef */
typedef dpart_struct_t *dpart_t;

/**
 * \brief The particle structure with double values itself.
 */
struct dpart_struct {
	/** Holds a pointer to the next particle */
	dpart_t next;
	/** The position */
	double pos[3];
	/** The momentum */
	double mom[3];
	/** The weight */
	double weight;
	/** The ID */
	part_id_t id;
};

/** Convenient typedef */
typedef struct spart_struct spart_struct_t;

/** Convenient typedef */
typedef spart_struct_t *spart_t;

/**
 * \brief The particle structure with float values itself.
 */
struct spart_struct {
	/** Holds a pointer to the next particle */
	spart_t next;
	/** The position */
	float pos[3];
	/** The momentum */
	float mom[3];
	/** The weight */
	float weight;
	/** The ID */
	part_id_t id;
};


/***********************************************************************\
 *    Prototypes of global functions                                   * 
\***********************************************************************/

/**
 * \brief Create a bunch of particles with double precision.
 *
 * \param num  Number of particles to create.
 *
 * \return An array with the requested number of particles, or NULL if
 *         not enough memory could be aquired.
 */
extern dpart_t
dpart_create(io_logging_t log, uint64_t num);

/**
 * \brief Create a bunch of particles with single precision.
 *
 * \param num  Number of particles to create.
 *
 * \return An array with the requested number of particles, or NULL if
 *         not enough memory could be aquired.
 */
extern spart_t
spart_create(io_logging_t log, uint64_t num);

/**
 * \brief Dispose a bunch of double precision particles.
 *
 * \param *parts  Pointer to the storage that holds the particles, will
 *                be set to NULL.
 *
 * \return Nothing.
 */
extern void
dpart_del(dpart_t *parts);

/**
 * \brief Dispose a bunch of single precision particles.
 *
 * \param *parts  Pointer to the storage that holds the particles, will
 *                be set to NULL.
 *
 * \return Nothing.
 */
extern void
spart_del(spart_t *parts);

/**
 * \brief Reduces the particle amount.
 *
 * \param log     A logging module.
 * \param parts   The particle storage of the full particle set.
 * \param num     The number of particles in the original set.
 * \param newnum  The new number of particles in the set.
 *
 * \return A reduced particle set.
 */
extern spart_t
spart_reduce(io_logging_t log,
             spart_t parts,
             uint64_t num,
             uint64_t newnum,
             unsigned int seed);

/**
 * \brief Scales the particle values by given factors.
 *
 * \param log       A logging module.
 * \param parts     The particle storage of the full particle set.
 * \param num       The number of particles in the set.
 * \param scpos     The scale factor for the position.
 * \param scmom     The scale factor for the momentum.
 * \param scweight  The scale factor for the weight.
 *
 * \returns The number of particles that got scaled.
 */
extern uint64_t
spart_scale(io_logging_t log,
            spart_t parts,
            uint64_t num,
            double scpos,
            double scmom,
            double scweight);

extern void
spart_dump(spart_t parts, uint64_t num);


#endif /* PART_H */
