/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
 * main.c
 * Copyright (C) 2013 Maurice 

Last version: 2013-01-29

In a D-cube, each dimension is divided into N intervals.
It defines N^D smaller D-cubes.
A "center" is selected by the user.
The program builds the list of the small D-cubes just around it
(at distance 1. Of course, it could be easily generalised).

This may be useful for some optimisation methods, which have to define areas
to avoid, or, on the contrary, to more finely explore.

WARNING
The way the cubes are stored is _very_ inefficient (the same components are
read and write several times)
This is on purpose, in order to have at each step a sequential file readable
by a human.
In practice, it would be of course far better to use direct access files.
	 * 
 * CubeGener is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
	 * 
 * CubeGener is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <stdio.h>
#define DMax 10
#define cubeNbMax 9 // 3^DMax

#define ERROR(a) {printf("\nERROR: %s\n", a);exit(-1);}

FILE * f[2];
//==============================================================================
int main()
{
	int centre[DMax];
	int cube[DMax];
	int d, D, d1,d2;
	int err;
	int fileR, fileW;
	int fsize[2];
	int i;
	int min[DMax],max[DMax];
	int n,N;
	int nCubeR,nCubeW;

	f[0] = fopen ("f0", "w");

	// The is supposed to be a cube
	// Each dimension is divided into N intervals
	N=4;
	D=4;
	centre[0]=4;
	centre[1]=4;
	centre[2]=4;
	centre[3]=4;
	centre[4]=4;
	//-------------------------- Check consistency
	if(D>DMax) ERROR("\n D is too big, you should increase DMax");

	err=0;
	for(d=0;d<D;d++)
	{
		if(centre[d]<1) 
		{
			printf("\n centre[%i] is wrong (%i)",d,centre[d]);
			err=1;
		}
		if(centre[d]>N)
		{
			printf("\n centre[%i] is wrong (%i)",d,centre[d]); 
			err=1;
		}
	}
	if(err>0) ERROR("Please check center[..]");

	//--------------------------Boundaries around the center
	for(d=0;d<D;d++) 
	{
		min[d]=centre[d]-1; if (min[d]<1) min[d]=1;
		max[d]=centre[d]+1; if(max[d]>N) max[d]=N;
	}

	//------------------------------------------------------------------------------
	// Write on the first file for D=1
	fileW=0;
	nCubeW=0;
	for(n=min[0];n<=max[0];n++)
	{
		fprintf(f[fileW],"%i\n",n);
		nCubeW++; 
	}
	printf("\n I have written %i partial cubes on file %i",nCubeW,fileW);
	if(D==1) goto end;

	for(d=1;d<D;d++)
	{
		// Reopen the written file as Read only, and open the other one as Writable
		switch(fileW)
		{
			case 0:
				fclose(f[0]);
				f[0] = fopen ("f0", "r");
				f[1] = fopen ("f1", "w");
				fileW=1; fileR=0;
				break;
			case 1:
				fclose(f[1]);
				f[1] = fopen ("f1", "r");
				f[0] = fopen ("f0", "w");
				fileW=0; fileR=1;
		}

		// Read the cubes (the first d components) on the first file
		// For each one, add one of the max[d]-min[d]+1 next possible component
		// and write the results on the second file
		nCubeR=nCubeW;
		printf("\n Reading %i cubes (d=%i), on file %i",nCubeR, d,fileR);
		nCubeW=0;
		for(n=0;n<nCubeR;n++)
		{
			for(i=0;i<d;i++) fscanf(f[fileR],"%i ",&cube[i]);

			// Generate
			for(d1=min[d];d1<=max[d];d1++)
			{
				cube[d]=d1;
				for(d2=0;d2<=d;d2++) fprintf(f[fileW],"%i ",cube[d2]);
				fprintf(f[fileW],"\n");
				//printf("\n");for(i=0;i<=d;i++) printf("%i ",cube[i]);
				nCubeW++; 
			}
		}
	}

	end:
		printf("\n The list of %i cubes is on the file f%i",nCubeW,fileW);
		return (0);
}
