COSTA: COSt and Termination Analyzer for Java Bytecode
    
    package x10;


public class KMeansDist {

    //static int DIM=2;
    //static int CLUSTERS=4;
    static final int POINTS=2000;
    static final int ITERATIONS=50;

    //static int points_region[][] = new int[POINTS-1][DIM-1];

    public static void main(String args[]) {
	
	int PLACES=args.length; //DZ: this is supposed to be static
				//(as the number of processors)
				//through the execution; anyway, we
				//leave it as a parameter


        //val rnd = PlaceLocalHandle.make[Random](Dist.makeUnique(), () => new Random(0));
        //val local_curr_clusters = PlaceLocalHandle.make[Rail[Float]](Dist.makeUnique(), 
	//() => Rail.make[Float](CLUSTERS*DIM, (i:Int) => 0 as Float));
	//val local_new_clusters = PlaceLocalHandle.make[Rail[Float]](Dist.makeUnique(),
	//() =>  Rail.make[Float](CLUSTERS*DIM, (i:Int) => 0 as Float));
        //val local_cluster_counts = PlaceLocalHandle.make[Rail[Int]](Dist.makeUnique(), 
        //                                                            ()=> Rail.make[Int](CLUSTERS, (i:Int) => 0));
	//int local_cluster_counts[];

        //val points_dist = Dist.makeBlock(points_region, 0);
        //val points = DistArray.make[Float](points_dist, (p:Point)=>rnd().nextFloat());

        //val central_clusters = Rail.make[Float](CLUSTERS*DIM, (i:Int) => {
	//val p = Point.make([i/DIM, i%DIM]);
	//return at (points_dist(p)) points(p);
	//});

        //val central_cluster_counts = Rail.make[Int](CLUSTERS, (i:Int) => 0); //DZ
	//int central_cluster_counts[] = new int[CLUSTERS];

        for (int i=1; i<=ITERATIONS; i++) {

            //int central_clusters_copy[];
	    //for (int j=0; j<CLUSTERS; j++) { central_clusters_copy[j] = central_cluster_counts[j]; };

            //for (int j=0; j<CLUSTERS; j++) { local_cluster_counts[][j] = 0; }

            Conc.finish_begin();
	    main_1(PLACES);
	    Conc.finish_end();

	    Conc.finish_begin();
	    main_2();
	    Conc.finish_end();


            //for (var j:Int=0 ; j<DIM*CLUSTERS ; ++j) {
	    //central_clusters(j) = 0;
	    //}

            //for (var j:Int=0 ; j<CLUSTERS ; ++j) {
	    //central_cluster_counts(j) = 0;
	    //}

	    Conc.finish_begin();
	    main_3(PLACES);
	    Conc.finish_end();

            //for (var k:Int=0 ; k<CLUSTERS ; ++k) { 
	    //for (var d:Int=0 ; d<DIM ; ++d) { 
	    //central_clusters(k*DIM+d) /= central_cluster_counts(k);
	    //}
            //}

            // TEST FOR CONVERGENCE
            //var b:Boolean = true;
            //for (var j:Int=0 ; j<CLUSTERS*DIM ; ++j) { 
	    //   if (Math.abs(central_clusters_copy(j)-central_clusters(j))>0.0001) {
            //        b = false;
            //        break;
            //    }
            //}
            //if (b) break;

        }
    }
    
    public static void main_1(int PLACES) {
	// reset state
	for (int d=0; d<PLACES; d++) {
	    Conc.async_begin(); // async(d) {
	    main_11();
	    Conc.async_end();
	}
    }
    
    public static void main_11() {
	//for (int j=0 ; j<DIM*CLUSTERS; j++) {
	//local_curr_clusters[][j] = central_clusters_copy[j];
	//local_new_clusters[][j] = 0;
	//}
	//for (int j=0 ; j<CLUSTERS; j++) {
	//local_cluster_counts[][j] = 0;
	//}
    }
    
    public static void main_2() {
	for (int p_=0; p_<POINTS; p_++) {
	    int p = p_;
	    Conc.async_begin();
	    main_21();
	    Conc.async_end();
	}
    }
    
    public static void main_21() {
	//async (points_dist(p,0)) {
	//var closest:Int = -1;
	//var closest_dist:Float = Float.MAX_VALUE;
	//for (var k:Int=0 ; k<CLUSTERS ; ++k) { 
	//var dist : Float = 0;
	//for (var d:Int=0 ; d<DIM ; ++d) { 
	//val tmp = points(Point.make(p,d)) - local_curr_clusters()(k*DIM+d);
	//dist += tmp * tmp;
	//}
	//if (dist < closest_dist) {
	//closest_dist = dist;
	//closest = k;
	//}
	//}
	//for (var d:Int=0 ; d<DIM ; ++d) { 
	//local_new_clusters()(closest*DIM+d) += points(Point.make(p,d));
	//}
	//local_cluster_counts()(closest)++;
	//}
    }
    
    public static void main_3(int PLACES) {
	for (int d=0; d<PLACES; d++) {
	    Conc.async_begin();
	    main_31();
	    Conc.async_end();
	}
    }
    
    public static void main_31() {
	//val local_new_clusters_copy =
	//ValRail.make(CLUSTERS*DIM, (i:Int) => local_new_clusters()(i));
	//val local_cluster_counts_copy =
	//ValRail.make(CLUSTERS, (i:Int) => local_cluster_counts()(i));
	//at (central_clusters) atomic {
	//for (var j:Int=0 ; j<DIM*CLUSTERS ; ++j) {
	//central_clusters(j) += local_new_clusters()(j);
	//}
	//for (var j:Int=0 ; j<CLUSTERS ; ++j) {
	//central_cluster_counts(j) += local_cluster_counts()(j);
	//}
	//}
    }
    

}