Index: /proiecte/Parallel-DT/R8/Src/build.c
===================================================================
--- /proiecte/Parallel-DT/R8/Src/build.c	(revision 101)
+++ /proiecte/Parallel-DT/R8/Src/build.c	(revision 102)
@@ -30,4 +30,12 @@
 MultiVal; /* true when all atts have many values */
 
+/* Variables for parallel version */
+ItemCount
+***Freq_discr, /* Freq_discr[tid][x][c] = no. items of class c with outcome x */
+**ValFreq_discr; /* ValFreq_discr[tid][x]   = no. items with outcome x */
+
+float
+**UnknownRate_discr; /* UnknownRate[tid][a] = current unknown rate for att a */
+
 /*  External variables initialised here  */
 
@@ -51,5 +59,5 @@
 /*  ------------------  */
 {
-	DiscrValue v;
+	DiscrValue v, i, nrThreads;
 	Attribute a;
 
@@ -100,5 +108,19 @@
 	}
 
-
+	/* Initializing parallel variables */
+	nrThreads = omp_get_max_threads();
+	Freq_discr = (ItemCount***) calloc (nrThreads, sizeof(ItemCount**));
+	ValFreq_discr = (ItemCount**) calloc (nrThreads, sizeof(ItemCount*));
+	UnknownRate_discr = (float**) calloc (nrThreads, sizeof(float*));
+
+	for(i = 0; i < nrThreads; i++){
+		Freq_discr[i] = (ItemCount **) calloc(MaxDiscrVal + 1, sizeof(ItemCount *));
+		ForEach(v, 0, MaxDiscrVal) {
+			Freq_discr[i][v] = (ItemCount *) calloc(MaxClass + 1, sizeof(ItemCount));
+		}
+
+		ValFreq_discr[i] = (ItemCount *) calloc(MaxDiscrVal + 1, sizeof(ItemCount));
+		UnknownRate_discr[i] = (float *) calloc(MaxAtt + 1, sizeof(float));
+	}
 }
 
@@ -158,22 +180,12 @@
 	/*  Generate the class frequency distribution  */
 
-	// ########### begin parallel region ############## //
-	//#pragma omp parallel default(shared)
-	//{
-
-		//printf("The parallel region is executed by thread %d\n", omp_get_thread_num());
-		/* THIS CAN BE PARALELIZED */
-		//#pragma omp for private(c)
-			ForEach(c, 0, MaxClass) {
-				ClassFreq[c] = 0;
-			}
-
-		/* THIS CAN BE PARALELIZED */
-		//#pragma omp for private(i)
-			ForEach(i, Fp, Lp) {
-				//#pragma omp atomic
-				ClassFreq[Class(Item[i])] += Weight[i];
-			}
-	//}
+	ForEach(c, 0, MaxClass) {
+		ClassFreq[c] = 0;
+	}
+
+	ForEach(i, Fp, Lp) {
+		ClassFreq[Class(Item[i])] += Weight[i];
+	}
+
 
 	/*  Find the most frequent class  */
@@ -358,33 +370,19 @@
 	ClassNo c, BestClass;
 	Tree Node, Leaf();
-	DiscrValue v;
+	DiscrValue v, thread_id;
 	Boolean PrevAllKnown;
-	ItemCount** Freq_discr, *ValFreq_discr;
-	float* UnknownRate_discr;
 
 	Cases = CountItems(Fp, Lp);
 
 	/*  Generate the class frequency distribution  */
-
-	// ########### begin parallel region ############## //
-	//#pragma omp parallel
-	//{
-		//printf("The parallel region is executed by thread %d\n", omp_get_thread_num());
-		/* THIS CAN BE PARALELIZED */
-		//#pragma omp for private(c)
-			ForEach(c, 0, MaxClass) {
-				ClassFreq[c] = 0;
-			}
-
-		/* THIS CAN BE PARALELIZED */
-		//#pragma omp for private(i)
-			ForEach(i, Fp, Lp) {
-				//#pragma omp atomic
-				ClassFreq[Class(Item[i])] += Weight[i];
-			}
-	//}
+	ForEach(c, 0, MaxClass) {
+		ClassFreq[c] = 0;
+	}
+
+	ForEach(i, Fp, Lp) {
+		ClassFreq[Class(Item[i])] += Weight[i];
+	}
 
 	/*  Find the most frequent class  */
-	/* THIS CAN BE PARALELIZED */
 	BestClass = 0;
 
@@ -412,16 +410,7 @@
 	/*  For each available attribute, find the information and gain  */
 	/* THIS MUST BE PARALELIZED */
-	#pragma omp parallel default(shared) shared(Possible, AvGain) private(v, Freq_discr, ValFreq_discr, UnknownRate_discr)
+	#pragma omp parallel if (Lp - Fp > 500) shared(Possible, AvGain) private(thread_id, Att)
 	{
-		Freq_discr = (ItemCount **) calloc(MaxDiscrVal + 1, sizeof(ItemCount *));
-		ForEach(v, 0, MaxDiscrVal) {
-			Freq_discr[v] = (ItemCount *) calloc(MaxClass + 1, sizeof(ItemCount));
-		}
-
-		ValFreq_discr = (ItemCount *) calloc(MaxDiscrVal + 1, sizeof(ItemCount));
-		UnknownRate_discr = (float *) calloc(MaxAtt + 1, sizeof(float));
-
-
-			#pragma omp for private(Att) schedule(static)
+			#pragma omp for private(Att) reduction(+:Possible, AvGain)
 			ForEach(Att, 0, MaxAtt) {
 				Gain[Att] = -Epsilon;
@@ -436,58 +425,47 @@
 							EvalSubset(Att, Fp, Lp, Cases);
 						} else if (!Tested[Att]) {
-
-							EvalDiscreteAtt_Discr(Att, Fp, Lp, Cases, Freq_discr, ValFreq_discr, UnknownRate_discr);
+							thread_id = omp_get_thread_num();
+							EvalDiscreteAtt_Discr(Att, Fp, Lp, Cases, Freq_discr[thread_id],
+									ValFreq_discr[thread_id], UnknownRate_discr[thread_id], &Gain[Att], &Info[Att]);
 						}
 					} else {
 						/*  continuous attribute  */
-
 						EvalContinuousAtt(Att, Fp, Lp);
 					}
 
 					/*  Update average gain, excluding attributes with very many values  */
-					#pragma omp critical
-					{
-						if (Gain[Att] > -Epsilon && (MultiVal || MaxAttVal[Att] < 0.3 * (MaxItem + 1))){
-							//#pragma omp atomic
-							Possible++;
-
-							//#pragma omp atomic
-							AvGain += Gain[Att];
-						}
+
+					if (Gain[Att] > -Epsilon && (MultiVal || MaxAttVal[Att] < 0.3 * (MaxItem + 1))){
+						//#pragma omp atomic
+						Possible++;
+
+						//#pragma omp atomic
+						AvGain += Gain[Att];
 					}
-			}
-
-			free(UnknownRate_discr);
-			free(ValFreq_discr);
-			ForEach(v, 0, MaxDiscrVal) {
-				free(Freq_discr[v]);
-			}
-			free(Freq_discr);
-
-	}
-
-		/*  Find the best attribute according to the given criterion  */
-		//#pragma omp single
-		//{
-			BestVal = -Epsilon;
-			BestAtt = None;
-			AvGain = (Possible ? AvGain / Possible : 1E6);
-
-			Verbosity(2) {
-				if (AvGain < 1E6)
-					printf("\taverage gain %.3f\n", AvGain);
-			}
-
-			ForEach(Att, 0, MaxAtt) {
-				if (Gain[Att] > -Epsilon) {
-					Val = Worth(Info[Att], Gain[Att], AvGain);
-					if (Val > BestVal) {
-						BestAtt = Att;
-						BestVal = Val;
-					}
-				}
-			}
-		//}
-	//}
+
+			}
+	}
+
+	/*  Find the best attribute according to the given criterion  */
+
+	BestVal = -Epsilon;
+	BestAtt = None;
+	AvGain = (Possible ? AvGain / Possible : 1E6);
+
+	Verbosity(2) {
+		if (AvGain < 1E6)
+			printf("\taverage gain %.3f\n", AvGain);
+	}
+
+	ForEach(Att, 0, MaxAtt) {
+		if (Gain[Att] > -Epsilon) {
+			Val = Worth(Info[Att], Gain[Att], AvGain);
+			if (Val > BestVal) {
+				BestAtt = Att;
+				BestVal = Val;
+			}
+		}
+	}
+
 	/*  Decide whether to branch or not  */
 
@@ -679,5 +657,4 @@
 	//Lwt = Weight + Lp;
 
-	//#pragma omp parallel for reduction(+:Sum)
 	for (i = Fp; i <= Lp; i++) {
 		Sum += Weight[i];
