#include "espresso.h"


/* cost -- compute the cost of a cover */
void cover_cost(pset_family F, pcost cost)
{
    register pcube p, last;
    pcube *T;
    int var;

    /* use the routine used by cofactor to decide splitting variables */
    massive_count(T = cube1list(F));
    free_cubelist(T);

    cost->cubes = F->count;
    cost->total = cost->in = cost->out = cost->mv = cost->primes = 0;

    /* Count transistors (zeros) for each binary variable (inputs) */
    for(var = 0; var < cube->num_binary_vars; var++)
    	cost->in += cdata->var_zeros[var];

    /* Count transistors for each mv variable based on sparse/dense */
    for(var = cube->num_binary_vars; var < cube->num_vars - 1; var++)
    	if (cube->sparse[var])
    	    cost->mv += F->count * cube->part_size[var] - cdata->var_zeros[var];
    	else
    	    cost->mv += cdata->var_zeros[var];

    /* Count the transistors (ones) for the output variable */
    if (cube->num_binary_vars != cube->num_vars) {
    	var = cube->num_vars - 1;
    	cost->out = F->count * cube->part_size[var] - cdata->var_zeros[var];
    }

    /* Count the number of nonprime cubes */
    foreach_set(F, last, p)
    	cost->primes += TESTP(p, PRIME) != 0;

    /* Count the total number of literals */
    cost->total = cost->in + cost->out + cost->mv;
}


/* fmt_cost -- return a string which reports the "cost" of a cover */
char *fmt_cost(pcost cost)
{
    static char s[200];

    if (cube->num_binary_vars == cube->num_vars - 1)
	(void) snprintf(s, sizeof(s), "c=%d(%d) in=%d out=%d tot=%d", 
	    cost->cubes, cost->cubes - cost->primes, cost->in,
	    cost->out, cost->total); /** MM: zmenene na secure version */
    else
	(void) snprintf(s, sizeof(s), "c=%d(%d) in=%d mv=%d out=%d",
	   cost->cubes, cost->cubes - cost->primes, cost->in,
	   cost->mv, cost->out); /** MM: zmenene na secure version */
    return s;
}


char *print_cost(pset_family F)
{
    cost_t cost;
    cover_cost(F, &cost);
    return fmt_cost(&cost);
}


/* copy_cost -- copy a cost function from s to d */
void copy_cost(pcost s, pcost d)
{
    d->cubes = s->cubes;
    d->in = s->in;
    d->out = s->out;
    d->mv = s->mv;
    d->total = s->total;
    d->primes = s->primes;
}


/* size_stamp -- print single line giving the size of a cover */
void size_stamp(pset_family T, char *name)
{
    if (tracesumoutput!=NULL){
        fprintf(tracesumoutput, "# %s\tCost is %s\n", name, print_cost(T));
        (void) fflush(tracesumoutput);
    }
}


/* print_trace -- print a line reporting size and time after a function */
/** MM: pridana kontrola parametra T */
void print_trace(pset_family T, const char *name, long int time)
{
    if (tracesumoutput!=NULL){
        fprintf(tracesumoutput, "# %s\tTime was %s, cost is ",
    	name, print_time(time));
    	if (T!=NULL) fprintf(tracesumoutput, "%s\n", print_cost(T)); /** MM: osetrenie, ak T nie je inicializovane - zrejme kvoli chybe pri alokacii alebo pri funkciach, pri ktorych muselo byt dealokovane skor kvoli memory-leaku */
    	else fprintf(tracesumoutput, "...\n");
        fflush(tracesumoutput);
    }
}


/* totals -- add time spent in the function into the totals */
/** MM: pridana kontrola parametra T */
void totals(long int time, int i, pset_family T, pcost cost)
{
    time = ptime() - time;
    total_time[i] += time;
    total_calls[i]++;
    if (T!=NULL) cover_cost(T, cost); /** MM: ak je T */
    if (trace) {
    	fprintf(tracesumoutput, "# %s\tTime was %s, cost is %s\n",
    	    total_name[i], print_time(time), fmt_cost(cost));
    	(void) fflush(tracesumoutput);
    }
}

/** MM: presunuta z main.cpp, aby bola pristupna aj z triedy PLA */
/** MM: volane len pri trace */
void
runtime(void)
{
    int i;
    long total = 1, temp;
    
    if (tracesumoutput==NULL) return; /** MM: ak nie je kam vypisovat */

    for(i = 0; i < TIME_COUNT; i++) {
    	total += total_time[i];
    }
    for(i = 0; i < TIME_COUNT; i++) {
    	if (total_calls[i] != 0) {
    	    temp = 100 * total_time[i];
    	    fprintf(tracesumoutput, "# %s\t%2d call(s) for %s (%2ld.%01ld%%)\n",
    		total_name[i], total_calls[i], print_time(total_time[i]),
    		    temp/total, (10 * (temp%total)) / total);
    	}
    }
}


/* fatal -- report fatal error message and take a dive */
/*void fatal(char *s)
{
    if (erroroutput!=NULL) fprintf(erroroutput, "espresso: %s\n", s);
    exit(-110);
}*/

/** MM: fatal2 je moja verzia - len vypise hlasku a funkcie si distribuuju informaciu o chybe sami */
void fatal2(char*s){
    if (erroroutput!=NULL){
        fprintf(erroroutput, "espresso: %s\n", s);
    }
    snprintf(errorbuffer, sizeof(errorbuffer), "%s", s); /** MM: pridane kvoli hlaske pre vynimku */
}
