/* interaction.c */

#include "interaction.h"
#include "Memory.h"
#include "debug.h"

#ifdef BETTER_MEMMAN
static STORAGE *interactionStor = (STORAGE *)NULL;
#define NEWINTERACTION()    (INTERACTION *)New(sizeof(INTERACTION), &interactionStor)
#define DISPOSEINTERACTION(ptr) Dispose((unsigned char *)(ptr), &interactionStor)

/* a separate pool for each possible number of coefficients in an interaction ... */
static STORAGE *couplingStor[BASISMAXSIZE*BASISMAXSIZE];
#define NEWCOUPLINGS(PQ)  	\
        PQ->K = (Float *)New(PQ->P->basis->size * PQ->Q->basis->size * sizeof(Float), \
			     &couplingStor[PQ->P->basis->size * PQ->Q->basis->size - 1])
#define DISPOSECOUPLINGS(PQ)   \
        Dispose((unsigned char *)(PQ->K), \
		&couplingStor[PQ->P->basis->size * PQ->Q->basis->size - 1])
#else /*BETTER_MEMMAN*/
#define NEWINTERACTION()	(INTERACTION *)Alloc(sizeof(INTERACTION))
#define DISPOSEINTERACTION(ptr) Free((char *)ptr, sizeof(INTERACTION))

#define NEWCOUPLINGS(PQ)	PQ->K = \
        (Float *)Alloc(PQ->P->basis->size * PQ->Q->basis->size * sizeof(Float))
#define DISPOSEINTERACTION(PQ) \
        Free((char *)(PQ->K), PQ->P->basis->size * PQ->Q->basis->size * sizeof(Float))
#endif /*BETTER_MEMMAN*/

/* copies the coupling coefficients from (Float **) K to (Float *) PQ->K, top to bottom,
 * left to right */
#define INITCOUPLINGS(PQ, K)	{int a,b; Float *p;			\
	for (p=PQ->K, a=0; a<PQ->P->basis->size; a++)			\
		for (b=0; b<PQ->Q->basis->size; b++, p++)		\
			*p = K[a][b];					\
}

/* prints the coupling coefficients */
#define PRINTCOUPLINGS(out, PQ)	{int a,b; Float *p;			\
	for (p=PQ->K, a=0; a<PQ->P->basis->size; a++) {			\
		for (b=0; b<PQ->Q->basis->size; b++, p++) {		\
			fprintf(out, "%g ", *p);			\
		}							\
                fprintf(out, "\n");					\
        }								\
}

static int TotalInteractions = 0;

int GetNumberOfInteractions(void)
{
	return TotalInteractions;
}

INTERACTION *InteractionCreate(PATCH *P, PATCH *Q, 
			       Float K[BASISMAXSIZE][BASISMAXSIZE], Float deltaK)
{
	INTERACTION *interaction;

	interaction = NEWINTERACTION();
	interaction->P = P;
	interaction->Q = Q;
	interaction->deltaK = deltaK;
	NEWCOUPLINGS(interaction);
	INITCOUPLINGS(interaction, K);

	TotalInteractions++;

	return interaction;
}

void InteractionDestroy(INTERACTION *interaction)
{
	DISPOSECOUPLINGS(interaction);
	DISPOSEINTERACTION(interaction);

	TotalInteractions--;
}

void InteractionPrint(FILE *out, INTERACTION *interaction)
{
	fprintf(out, "%d -> %d: deltaK = %g, K[a,b],a=0..%d,b=0..%d = %s", 
		interaction->P->id, interaction->Q->id, interaction->deltaK, 
		interaction->P->basis->size-1, interaction->Q->basis->size-1,
		interaction->P->basis->size > 1 ? "\n" : "");
		
	PRINTCOUPLINGS(out, interaction);
	fprintf(out, "\n");
}

