#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "base.h"
#include "factor.h"
#include "cost_function.h"

/* This is for virus scanning */
#if 0
int build_cost_functions(struct FactorSet *fs, struct CostFunction *cf, int size)
{
	float N_total = fs->N_input + fs->N_output;

	/* Time & Energy in mobile CPU */
	cf->T_cpu = (fs->t_comp*fs->U_cpu)/fs->U_cpu;		/* us */
	cf->E_cpu = cf->T_cpu * (fs->P_cpu+fs->P_basic);

	/* temp */
	cf->T_cop = 999999999.0f;
	cf->E_cop = 999999999.0f;
	
	/* Consider the limitation of size, i.e. the maximum size of ethernet is 1514 bytes */
	int num_of_packets = 0;
	float trans_time = 0.0f;
	num_of_packets = fs->N_input/1448 + 1;
	printf("input: %f output: %f\n", fs->N_input, fs->N_output);
	printf("num of packets: %d\n", num_of_packets);
	trans_time = (num_of_packets*1514*8/(fs->B_tx*1))*1000 + (1*1514*4/(fs->B_rx*1))*1000
		+ ((3+num_of_packets+4)*66*8/(fs->B_tx*1))*1000;
	printf("transmission time: %f\n", trans_time);
	cf->T_cld = (8*N_total/fs->U_mem) + (fs->t_comp*fs->U_cpu)/fs->U_cld + trans_time;
	cf->E_cld = (cf->T_cld-trans_time) * fs->P_basic + trans_time * (fs->P_nic+fs->P_basic);

	printf("\t ------------------------------------------\n");
	printf("\t| CPU   cost %10.3f\tus %10.3f\tmJ |\n", cf->T_cpu, cf->E_cpu/1000);
	printf("\t| GPU   cost %10.3f\tus %10.3f\tmJ |\n", cf->T_cop, cf->E_cop/1000);
	printf("\t| CLOUD cost %10.3f\tus %10.3f\tmJ |\n", cf->T_cld, cf->E_cld/1000);
	printf("\t ------------------------------------------\n");
	/* Write to log file */
	FILE *fptr = fopen("Docs/exec-log", "a");
	fprintf(fptr, "Estimate CPU/GPU/CLOUD cost\t [ %f %f %f ]\tus,\t", cf->T_cpu, cf->T_cop, cf->T_cld);
	fclose(fptr);

	return 0;
}
#endif

/*
 * @Function:		build_cost_functions
 * @Return:			0 when success
 * @Description:	
 */
int build_cost_functions(struct FactorSet *fs, struct CostFunction *cf, int size)
{
	float N_total = fs->N_input + fs->N_output;
	int n = size/4;

	/* Time & Energy in mobile CPU */
	cf->T_cpu = (fs->t_comp*n*n*n*fs->U_cpu)/fs->U_cpu;		/* us */
	cf->E_cpu = cf->T_cpu * (fs->P_cpu+fs->P_basic);
	
	/* Time & Energy in mobile GPU */
	float setup_time = 150000;
	cf->T_cop = (8*N_total/fs->U_mem) + (fs->t_comp*n*n*n*fs->U_cpu)/fs->U_cop + setup_time;	/* us */
	cf->E_cop = (cf->T_cop-setup_time) * (fs->P_cop+fs->P_basic) + setup_time * fs->P_basic;

	/* Consider the limitation of size, i.e. the maximum size of ethernet is 1514 bytes */
	int num_of_packets = 0;
	float trans_time = 0.0f;
	num_of_packets = fs->N_input/1448 + 1;
	printf("input: %f output: %f\n", fs->N_input, fs->N_output);
	printf("num of packets: %d\n", num_of_packets);
	trans_time = (num_of_packets*1514*8/(fs->B_tx*1))*1000 + (num_of_packets*1514*4/(fs->B_rx*1))*1000
		+ ((3+num_of_packets+4)*66*8/(fs->B_tx*1))*1000;
	printf("transmission time: %f\n", trans_time);
	cf->T_cld = (8*N_total/fs->U_mem) + (fs->t_comp*n*n*n*fs->U_cpu)/fs->U_cld + trans_time;
	cf->E_cld = (cf->T_cld-trans_time) * fs->P_basic + trans_time * (fs->P_nic+fs->P_basic);

	printf("\t ------------------------------------------\n");
	printf("\t| CPU   cost %10.3fus %10.3fmJ |\n", cf->T_cpu, cf->E_cpu/1000);
	printf("\t| GPU   cost %10.3fus %10.3fmJ |\n", cf->T_cop, cf->E_cop/1000);
	printf("\t| CLOUD cost %10.3fus %10.3fmJ |\n", cf->T_cld, cf->E_cld/1000);
	printf("\t ------------------------------------------\n");
	/* Write to log file */
	FILE *fptr = fopen("Docs/exec-log", "a");
	fprintf(fptr, "Estimate CPU/GPU/CLOUD cost [ %f %f %f ]us  [ %f %f %f ]mJ,\t", cf->T_cpu, cf->T_cop, cf->T_cld, cf->E_cpu, cf->E_cop, cf->E_cld);
	fclose(fptr);

	return 0;
}

