int GetNewFace(INPUT_DESC *input, int nDirection)
{
	char strFileName[128];

	if (nDirection == DIRECTION_FORWARD)
		g_nPoseID++;
	else
		g_nPoseID--;


	while (GetNextFileName(strFileName, nDirection))
		;

	if (ReadFaceInput(input, strFileName))
		return (-1);
			
	check_input_bounds (input, input->wx + input->ww/2, input->wy + input->wh/2);
	input->up2date = 0;
	update_input_neurons (input);
	update_input_image (input);

	input->green_cross_x = g_nLeftEyeX;
	input->green_cross_y = g_nLeftEyeY;
	g_nPos = 0;
	
	return (0);
}
NEURON_OUTPUT GetFace2 (PARAM_LIST *pParamList)
{
	NEURON_OUTPUT output;
	char strFileName[256];
	
	g_nPersonUniqueID = g_nPersonID = pParamList->next->param.ival;
	g_nIllumination = pParamList->next->next->param.ival;
	
	if (!check_person_parameters ("GetFace2()"))
	{
		output.ival = -1;
		return (output);
	}
	
	sprintf(strFileName, "%s%s%s.raw", INPUT_PATH, g_chPersonID[g_nPersonID], g_chIllumination[g_nIllumination]);
	printf ("%02d %02d - FileName: %s\n", g_nPersonID, g_nIllumination, strFileName);
	fflush(stdout);
	
	if (ReadFaceInput (&face_recog, strFileName))
	{
		printf ("### Error in GetRandomFace(): Cannot read face '%s'.\n", strFileName);
		output.ival = -1;
		return (output);
	}
	
	check_input_bounds (&face_recog, face_recog.wx + face_recog.ww/2, face_recog.wy + face_recog.wh/2);
	face_recog.up2date = 0;
	update_input_neurons (&face_recog);
	update_input_image (&face_recog);
		
	output.ival = 0;
	return (output);
}
NEURON_OUTPUT GetRandomFaceN (int nRandomFace)
{
	NEURON_OUTPUT output;
	char strFileName[256];
	FILE *pFile = NULL;
	int i;
	
	if ((pFile = fopen (g_strRandomFacesFileName, "r")) == NULL)
	{
		printf ("Error: cannot open file '%s' (GetRandomFace).\n", g_strRandomFacesFileName);
		output.ival = -1;
		return (output);
	}
	
	for (i = 0; i < nRandomFace; i++)
		fscanf (pFile, "%d %c %d %d\n", &g_nPersonUniqueID, &g_cSexID, &g_nPersonID, &g_nPoseID);
	fclose (pFile);
	
	if ((g_cSexID != 'm') && (g_cSexID != 'w'))
	{
		printf ("Error: Invalid sex ID, it must be 0 for man or 1 for woman (GetRandomFace).\n");
		output.ival = -1;
		return (output);
	}
	
	g_nMaxPersonID = (g_cSexID == 'm') ? MAX_MAN_ID : MAX_WOMAN_ID;
	if ((g_nPersonID < MIN_PERSON_ID) || (g_nPersonID > g_nMaxPersonID))
	{
		printf ("Error: Invalid person ID, it must be within the interval [%d, %d] (GetRandomFace).\n", MIN_PERSON_ID, g_nMaxPersonID);
		output.ival = -1;
		return (output);
	}
	
	if ((g_nPoseID < POSE_MIN) || (g_nPoseID > POSE_MAX))
	{
		printf ("Error: Invalid pose ID, it must be within the interval [%d, %d] (GetRandomFace).\n", POSE_MIN, POSE_MAX);
		output.ival = -1;
		return (output);
	}
	
	sprintf(strFileName, "%s%c-%03d-%d.raw", INPUT_PATH, g_cSexID, g_nPersonID, g_nPoseID);
	printf("FileName: %s\n", strFileName);
	fflush(stdout);
	
	if (ReadFaceInput (&face_recog, strFileName))
	{
		printf ("Error: Cannot read face (GetRandomFace).\n");
		output.ival = -1;
		return (output);
	}
		
	check_input_bounds (&face_recog, face_recog.wx + face_recog.ww/2, face_recog.wy + face_recog.wh/2);
	face_recog.up2date = 0;
	update_input_neurons (&face_recog);
	update_input_image (&face_recog);
		
	output.ival = 0;
	return (output);
}
void
update_input_layer_neurons_and_image_light(INPUT_DESC *input)
{
	check_input_bounds (input, input->wx + input->ww/2, input->wy + input->wh/2);
	input->up2date = 0;
	update_input_neurons (input);
	update_input_image (input);
}
// Update the input layer neurons and Image
void
update_input_layer_neurons_and_image(INPUT_DESC *input)
{
	check_input_bounds (input, input->wx + input->ww/2, input->wy + input->wh/2);
	input->up2date = 0;
	update_input_neurons (input);
	update_input_image (input);
	
	input_filters_and_outputs_update();
}
NEURON_OUTPUT GetFace (PARAM_LIST *pParamList)
{
	NEURON_OUTPUT output;
	char strFileName[256];
	
	g_cSexID    = (pParamList->next->param.ival) ? 'w' : 'm';
	g_nPersonID = pParamList->next->next->param.ival;
	g_nPoseID   = pParamList->next->next->next->param.ival;

	if ((g_cSexID != 'm') && (g_cSexID != 'w'))
	{
		printf ("Error: Invalid sex ID, it must be 0 for man or 1 for woman (GetFace).\n");
		output.ival = -1;
		return (output);
	}
	
	g_nMaxPersonID = (g_cSexID == 'm') ? MAX_MAN_ID : MAX_WOMAN_ID;
	if ((g_nPersonID < MIN_PERSON_ID) || (g_nPersonID > g_nMaxPersonID))
	{
		printf ("Error: Invalid person ID, it must be within the interval [%d, %d] (GetFace).\n", MIN_PERSON_ID, g_nMaxPersonID);
		output.ival = -1;
		return (output);
	}
	
	if ((g_nPoseID < POSE_MIN) || (g_nPoseID > POSE_MAX))
	{
		printf ("Error: Invalid pose ID, it must be within the interval [%d, %d] (GetFace).\n", POSE_MIN, POSE_MAX);
		output.ival = -1;
		return (output);
	}
	
	sprintf(strFileName, "%s%c-%03d-%d.raw", INPUT_PATH, g_cSexID, g_nPersonID, g_nPoseID);
	printf("FileName: %s\n", strFileName);
	fflush(stdout);
	
	if (ReadFaceInput (&face_recog, strFileName))
	{
		printf ("Error: Cannot read face (GetFace).\n");
		output.ival = -1;
		return (output);
	}	
	
	check_input_bounds (&face_recog, face_recog.wx + face_recog.ww/2, face_recog.wy + face_recog.wh/2);
	face_recog.up2date = 0;
	update_input_neurons (&face_recog);
	update_input_image (&face_recog);

	g_nPersonUniqueID = g_nPersonID * 2 - ((g_cSexID == 'w') ? 0 : 1);
	printf ("g_nPersonID = %d, g_cSexID = %d, g_nPersonUniqueID = %d\n", g_nPersonID, g_cSexID, g_nPersonUniqueID);
	output.ival = 0;
	return (output);
}
void
get_new_char(INPUT_DESC *input, int direction)
{
	g_label = (int) read_char_input(input, char_label_file, char_image_file, direction);
	check_input_bounds(input, input->wx + input->ww / 2, input->wy + input->wh / 2);

	update_input_image(input);

	glutSetWindow(input->win);
	glBindTexture(GL_TEXTURE_2D,(GLuint) input->tex);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, input->tfw, input->tfh, 0, GL_RGB, GL_UNSIGNED_BYTE, input->image);
	glutPostWindowRedisplay(input->win);
}
NEURON_OUTPUT GetDoc (PARAM_LIST *pParamList)
{
	NEURON_OUTPUT output;
	char strFileName[256];
	int nDoc;
	int mode;
	int nDirection;
	int first_access; 

	nDoc = pParamList->next->param.ival;
	mode = pParamList->next->next->param.ival;
	first_access = pParamList->next->next->next->param.ival;
	
	if(mode == LINEAR_MODE)
	{
		if(first_access)
		{
			g_nDocNumber = nDoc;
			nDirection = NO_DIRECTION;
		}
		else
			nDirection = DIRECTION_FORWARD;
	}
	else    //RANDOM_MODE
	{
		g_nDocNumber = (random() % DOC_MAX) + 1;
		nDirection = NO_DIRECTION;
	}
	
	while (GetNextFileName(strFileName, nDirection))
		;
	
	if (ReadDocumentInput(&document, strFileName))
	{
		printf ("Error: Cannot read document (GetDoc).\n");
		output.ival = -1;
		return (output);
	}
	
	update_input_image (&document);
	check_input_bounds (&document, document.wx + document.ww/2, document.wy + document.wh/2);

	output.ival = 0;
	
	return (output);
}
NEURON_OUTPUT GetItem (PARAM_LIST *pParamList)
{
	char file_name[256];
	FILE *File;
	NEURON_OUTPUT output;
	int item_number, data_base;

	item_number = pParamList->next->param.ival;
	data_base = pParamList->next->next->param.ival;

	sprintf (file_name, "%s%d.pnm", (data_base == CNAE_TABLE_ID)? CNAE_TABLE_PATH: OBJETOS_SOCIAIS_PATH, item_number);
	
	if ((File = fopen (file_name, "r")) == NULL)
	{
		fclose (File);
		show_message ("Could not get item", file_name, " in GetItem ()");
		output.ival = -1;
		return (output);
	}
	fclose (File);

	if (ReadDocumentInput(&document, file_name))
	{
		show_message ("Could not read document ", file_name, " in GetItem ()");
		output.ival = -1;
		return (output);
	}

	g_nDocNumber = item_number;
	g_nDataBaseId = data_base;
	printf ("FileName: %s\n", file_name);
	fflush (stdout);
	
	update_input_image (&document);
	check_input_bounds (&document, document.wx + document.ww/2, document.wy + document.wh/2);

	output.ival = 0;
	
	return (output);
}
void
rbm_filter(FILTER_DESC *filter_desc)
{
	PARAM_LIST *p_list = NULL;
	NEURON_LAYER_LIST *n_list = NULL;
	int nl_number, p_number;
	NEURON_LAYER *nl_output = NULL, *nl_input = NULL;
	int wo, ho;
	int wi, hi;
	int xo, yo;
	int xi, yi;
	BoltzmannMachine *network;
	BoltzmannMachine **p_network;

	// Checks the number of input Neuron Layers
	for (nl_number = 0, n_list = filter_desc->neuron_layer_list; n_list != NULL; n_list = n_list->next, nl_number++)
       		;

	// Checks the number of Parameters
	for (p_number = 0, p_list = filter_desc->filter_params; p_list != NULL; p_list = p_list->next, p_number++)
      		;

	// Gets the Input Neuron Layer
	nl_input = filter_desc->neuron_layer_list->neuron_layer;

	wi = nl_input->dimentions.x;
	hi = nl_input->dimentions.y;

	// Gets the Filter Output
	nl_output = filter_desc->output;

	wo = nl_output->dimentions.x;
	ho = nl_output->dimentions.y;

	if (*((int *)filter_desc->filter_params->next->param.pval) == 0)
	{
		network = new BoltzmannMachine(wi * hi, wo * ho, filter_desc->filter_params->next->next->param.ival);
		p_network = (BoltzmannMachine **) &(filter_desc->filter_params->next->param.pval);
		*p_network = network;
	}
	else
	{
		network = (BoltzmannMachine *) filter_desc->filter_params->next->param.pval;
	}

	if (g_state == READ)
	{
		double data[INPUT_WIDTH * INPUT_HEIGHT];

		for (yi = 0; yi < hi; yi++)
			for (xi = 0; xi < wi; xi++)
				data[yi * wi + xi] = ( ((float)nl_input->neuron_vector[yi * wi + xi].output.ival) / 255.0);

		network->read_data(data, INPUT_WIDTH * INPUT_HEIGHT);
	}
	else if (g_state == TRAIN)
	{
		network->train_network();
	}
	else if (g_state == TRAIN_STEP)
	{
		network->train_step(10);

		for (yo = 0; yo < ho; yo++)
			for (xo = 0; xo < wo; xo++)
				nl_output->neuron_vector[yo * wo + xo].output.fval = (float) (network->get_hidden_neuron_value(yo * wo + xo));

		update_output_image(get_output_by_neural_layer(nl_output));

		for (yi = 0; yi < hi; yi++)
			for (xi = 0; xi < wi; xi++)
				nl_input->neuron_vector[yi * wi + xi].output.ival = (int) (network->get_visible_neuron_value(yi * wi + xi) * 255.0);
		
		update_input_image(get_input_by_neural_layer(nl_input));
	}
	else if (g_state == ANNEALING_TEST)
	{
		network->annealing_test();

		for (yo = 0; yo < ho; yo++)
			for (xo = 0; xo < wo; xo++)
				nl_output->neuron_vector[yo * wo + xo].output.fval = (float) (network->get_hidden_neuron_value(yo * wo + xo));

		update_output_image(get_output_by_neural_layer(nl_output));

		for (yi = 0; yi < hi; yi++)
			for (xi = 0; xi < wi; xi++)
				nl_input->neuron_vector[yi * wi + xi].output.ival = (int) (network->get_visible_neuron_value(yi * wi + xi) * 255.0);
		
		update_input_image(get_input_by_neural_layer(nl_input));
	}
	else if (g_state == SET_AND_TEST)
	{
		for (yi = 0; yi < hi; yi++)
			for (xi = 0; xi < wi; xi++)
				network->set_visible_neuron_value(yi * wi + xi, ((float)nl_input->neuron_vector[yi * wi + xi].output.ival) / 255.0);
		
		network->test_network(100);

		for (yo = 0; yo < ho; yo++)
			for (xo = 0; xo < wo; xo++)
				nl_output->neuron_vector[yo * wo + xo].output.fval = (float) (network->get_hidden_neuron_value(yo * wo + xo));

		update_output_image(get_output_by_neural_layer(nl_output));

		for (yi = 0; yi < hi; yi++)
			for (xi = 0; xi < wi; xi++)
				nl_input->neuron_vector[yi * wi + xi].output.ival = (int) (network->get_visible_neuron_value(yi * wi + xi) * 255.0);
		
		update_input_image(get_input_by_neural_layer(nl_input));
	}
	else if (g_state == UNLOAD_LEARNING)
	{
		network->unload("character.dump");
	}
	else if (g_state == RELOAD_LEARNING)
	{
		network->reload("character.dump");
	}
}