std::pair<testing_result_smart_ptr, training_stat_smart_ptr> network_updater::update(
		supervised_data_reader& reader,
		const std::vector<std::vector<float> >& learning_rates,
		network_data_smart_ptr data,
		unsigned int batch_size,
		float weight_decay,
		float momentum,
		const std::map<unsigned int, float>& layer_to_dropout_rate_map)
	{
		// Check data-schema consistency
		data->check_network_data_consistency(*schema);

		set_input_configuration_specific(reader.get_input_configuration());

		// Check schema-reader consistency
		layer_config_list[layer_config_list.size() - 1].check_equality(reader.get_output_configuration());

		nnforge_uniform_real_distribution<float> dist(0.0F, 1.0F);
		for(std::vector<float>::iterator it = random_uniform_list.begin(); it != random_uniform_list.end(); ++it)
			*it = dist(gen);

		std::pair<testing_result_smart_ptr, training_stat_smart_ptr> res = actual_update(reader, learning_rates, data, batch_size, weight_decay, momentum, layer_to_dropout_rate_map);

		return res;
	}
void stack_widget_update(StackWidget *sw)
{
	/* We need all of it in order to update the widget! */
	if(!sw->read_sp_callback || !sw->ram_read_callback || !sw->cpu || !sw->ram)
		return;
	
	sw->sp = sw->read_sp_callback(sw->cpu);
	actual_update(sw);
}
void scroll_down(StackWidget *sw)
{
	/* See scroll_up() */
	if(sw->sp <= (STACK_WIDGET_ROWS / 2))
		sw->sp = STACK_WIDGET_ROWS / 2 - 1;
	else if(sw->sp >= 0x100 - (STACK_WIDGET_ROWS / 2))
		sw->sp = 0xFF -( STACK_WIDGET_ROWS / 2);
	else
		sw->sp -= 1;
	actual_update(sw);
}
void scroll_up(StackWidget *sw)
{
	/* 
	 * Yeah, this might be unclear, but the stack pointer of the CPU is of
	 * course not updated, only the internal one of this widget
	 */
	if(sw->sp >= 0x100 - (STACK_WIDGET_ROWS / 2))
		sw->sp = 0xFF - (STACK_WIDGET_ROWS / 2);
	else if(sw->sp < STACK_WIDGET_ROWS / 2)
		sw->sp = STACK_WIDGET_ROWS / 2;
	else
		sw->sp += 1;
	actual_update(sw);
}