public static SeqDist getClosestInFile(int[] u, File file) throws IOException {
		/*
		 *  ///!!!\\\ all the sequences in the file must have the same size
		 */
		
		DnaFileReader reader = new DnaFileReader(file);
		int nSeq = reader.totalNumberofSeq();
		int[] bestSeq = null, curSeq = null;
		int bestDist = Integer.MAX_VALUE;
		int[] t = reader.readSequence();
		
		// Enable exceptions and omit all subsequent error checks
        JCudaDriver.setExceptionsEnabled(true);

        // Create the PTX file by calling the NVCC
        String ptxFileName = preparePtxFile("edition_distance/DnaDistanceKernel.cu");

        // Initialize the driver and create a context for the first device.
        cuInit(0);
        CUdevice device = new CUdevice();
        cuDeviceGet(device, 0);
        CUcontext context = new CUcontext();
        cuCtxCreate(context, 0, device);

        // Load the ptx file.
        CUmodule module = new CUmodule();
        cuModuleLoad(module, ptxFileName);

        // Obtain a function pointer to the "add" function.
        CUfunction function = new CUfunction();
        cuModuleGetFunction(function, module, "distance");
        
		// ensures u.length >= t.length
        if (u.length < t.length){
        	int[] tmp = u;
        	u = t;
        	t = tmp;
        }
        
        int kmax = u.length + t.length ;
        int diagSize = t.length + 1;
        
        // prepare host diags to copy
        int[] hostDiag1 = {0};
        int[] hostDiag2 = {1, 1};
        
        // Allocate the device inputs
        CUdeviceptr deviceInputU = new CUdeviceptr();
        cuMemAlloc(deviceInputU, u.length * Sizeof.INT);
        CUdeviceptr deviceInputT = new CUdeviceptr();
        cuMemAlloc(deviceInputT, t.length * Sizeof.INT);
        
        // Allocate the device diags
        CUdeviceptr deviceDiag0 = new CUdeviceptr();
        cuMemAlloc(deviceDiag0, diagSize * Sizeof.INT);
        CUdeviceptr deviceDiag1 = new CUdeviceptr();
        cuMemAlloc(deviceDiag1, diagSize * Sizeof.INT);
        CUdeviceptr deviceDiag2 = new CUdeviceptr();
        cuMemAlloc(deviceDiag2, diagSize * Sizeof.INT);
        
        int blockSizeX = 672;
        int[] res = new int[1];
        int finalDiag = (kmax+1) % 3;
		
		for(int i = 0 ; i < nSeq ; i++){
			if (i != 0){
				t = reader.readSequence();
				// ensures u.length >= t.length
		        if (u.length < t.length){
		        	int[] tmp = u;
		        	u = t;
		        	t = tmp;
		        }
			}

	        cuMemcpyHtoD(deviceInputU, Pointer.to(u), u.length * Sizeof.INT);
	        cuMemcpyHtoD(deviceInputT, Pointer.to(t), t.length * Sizeof.INT);
	        
	        cuMemcpyHtoD(deviceDiag1, Pointer.to(hostDiag1), Sizeof.INT);
	        cuMemcpyHtoD(deviceDiag2, Pointer.to(hostDiag2), 2 * Sizeof.INT);
	        
	        // Set up the kernel parameters: A pointer to an array
	        // of pointers which point to the actual values.
	        Pointer kernelParameters = Pointer.to(
	    		Pointer.to(new int[]{u.length}),
	    		Pointer.to(new int[]{t.length}),
	    		Pointer.to(new int[]{kmax}),
	            Pointer.to(deviceInputU),
	            Pointer.to(deviceInputT),
	            Pointer.to(deviceDiag0),
	            Pointer.to(deviceDiag1),
	            Pointer.to(deviceDiag2)
	        );

	        // Call the kernel function.
	        cuLaunchKernel(function,
	            1,  1, 1,      // Grid dimension
	            blockSizeX, 1, 1,      // Block dimension
	            0, null,               // Shared memory size and stream
	            kernelParameters, null // Kernel- and extra parameters
	        );
	        cuCtxSynchronize();

	        // Allocate host output memory and copy the device diag2 to the host
	        switch(finalDiag){
	        case 0:
	        	cuMemcpyDtoH(Pointer.to(res), deviceDiag0.withByteOffset(t.length * Sizeof.INT), Sizeof.INT);
	        	break;
	        case 1:
	        	cuMemcpyDtoH(Pointer.to(res), deviceDiag1.withByteOffset(t.length * Sizeof.INT), Sizeof.INT);
	        	break;
	        case 2:
	        	cuMemcpyDtoH(Pointer.to(res), deviceDiag2.withByteOffset(t.length * Sizeof.INT), Sizeof.INT);
	        	break;
	        }
	        
	        System.err.println("Processed distance #" + i +": "+res[0]);
	        
			if (res[0] < bestDist){
				bestSeq = curSeq;
				bestDist = res[0];
			}
		}
		
		// Clean up.
        cuMemFree(deviceInputU);
        cuMemFree(deviceInputT);
        cuMemFree(deviceDiag0);
        cuMemFree(deviceDiag1);
        cuMemFree(deviceDiag2);
		
		return new SeqDist(bestSeq, bestDist);
	}