Exemple #1
0
BOOL PtEmtFiles::LoadPFile(LPCTSTR szFileName)
{
	FILE *fp = _tfopen(szFileName, _T("rt"));
	if (NULL == fp)	{
		return FALSE;
	}
	
	FLOAT real, imag;
	m_PData.clear();
	for(SHORT i = 0; i < TotalDirNum; i++)	{
		A_COMPLEX ATemp;
		for(SHORT j = 0; j < DetectorNum; j++)	{
			_ftscanf(fp, _T("%f,%f\n"), &real, &imag);
			ATemp.push_back(COMPLEX(real, imag));
		}
		m_PData.push_back(ATemp);
	}
	fclose(fp);
	return TRUE;
}
Exemple #2
0
BOOL PtEmtFiles::LoadGrayFile(LPCTSTR szFileName)
{
	m_bGrayOK = FALSE;
	FILE *fp = _tfopen(szFileName, _T("rt"));
	if (NULL == fp)	{
		return FALSE;
	}
	
	UINT temp;
	FLOAT fTemp;
	m_MGray.clear();
	for (SHORT i = 0; i < TotalElement; i++) {
		_ftscanf(fp, _T("%d    %f\n"), &temp, &fTemp);
		if (fTemp < 0)	{
			fTemp = 0.0;
		}
		m_MGray.push_back(fTemp);
	}
	fclose(fp);

	m_bGrayOK = TRUE;
	return m_bGrayOK;
}
int _tmain(int argc, LPTSTR argv[]) {

	HANDLE hIn, hOut;
	DWORD nIn, nOut, n;
	BOOL finish = FALSE;
	TCHAR input[L];
	TCHAR cmd;
	LARGE_INTEGER offset;
	Student s;

	/* Check number of arguments */
	if(argc != 2) {
		_ftprintf(stderr, _T("Wrong number of arguments. Usage: %s fileIn\n"), argv[0]);
		return -1;
	}

	while (!finish) {
		_ftprintf(stdout, _T("Enter a command:\n"));
		_fgetts(input, L, stdin);
		
		cmd = input[0];

		/* Case E */
		if (cmd == 'E') {
			finish = TRUE;
		}

		/* Case R */
		if (cmd == 'R') {
			_stscanf(input, _T("%*c %i"), &n);

			hIn = CreateFile(argv[1], GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
			if (hIn == INVALID_HANDLE_VALUE) {
				_ftprintf(stderr, _T("Error opening the file for reading: %i\n"), GetLastError());
				return -2;
			}

			if (n > 1) {
				offset.QuadPart = (n - 1) * sizeof(Student);

				if (!SetFilePointerEx(hIn, offset, NULL, FILE_BEGIN)) {
					_ftprintf(stderr, _T("Error setting the pointer: %i\n"), GetLastError());
					return -3;
				}
			}

			if (ReadFile(hIn, &s, sizeof(Student), &nIn, NULL) && (nIn > 0)) {
				_ftprintf(stdout, _T("%i %i %s %s %i\n"), s.id, s.number, s.name, s.surname, s.mark);
			} else {
				_ftprintf(stderr, _T("Error reading the file: %i\n"), GetLastError());
				return -4;
			}

			CloseHandle(hIn);

		}

		/* Case W */
		if (cmd == 'W') {
			_stscanf(input, _T("%*c %i"), &n);

			hOut = CreateFile(argv[1], GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
			if (hOut == INVALID_HANDLE_VALUE) {
				_ftprintf(stderr, _T("Error opening the file for writing: %i\n"), GetLastError());
				return -5;
			}

			_ftprintf(stdout, _T("Enter a new record:\n"));
			_ftscanf(stdin, _T("%i %i %s %s %i"), &s.id, &s.number, s.name, s.surname, &s.mark);

			if (n > 1) {
				offset.QuadPart = (n - 1) * sizeof(Student);

				if (!SetFilePointerEx(hOut, offset, NULL, FILE_BEGIN)) {
					_ftprintf(stderr, _T("Error setting the pointer: %i\n"), GetLastError());
					return -6;
				}
			}

			if (!WriteFile(hOut, &s, sizeof(Student), &nOut, NULL) || (nOut != sizeof(Student))) {
				_ftprintf(stderr, _T("Error writing the file: %i\n"), GetLastError());
				return -7;
			}

			CloseHandle(hOut);
		}
	}

	return 0;
}
INT convertAcount(INT argc, LPTSTR argv[]) {
	FILE* inputFile;
	HANDLE hOut;
	DWORD nOut;

	if (argc != 3) {
		_ftprintf(stderr, _T("Wrong number of arguments.\n Usage : %s inputFile outputFile"), argv[0]);
		return 1;
	}

	inputFile = _tfopen(argv[1], _T("r"));
	if (inputFile == NULL) {
		_ftprintf(stderr, _T("error when opening input file, errno = %i\n"), errno);
		return 1;
	}

	hOut = CreateFile(argv[2], GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hOut == INVALID_HANDLE_VALUE) {
		fprintf(stderr, "Error %i when opening second file", GetLastError());
		fclose(inputFile);
		return 1;
	}

	Record  record;
	//Actual conversion from ASCII to binary format
	while (_ftscanf(inputFile, _T("%i %i %s %s %i"), &record.lineNumber, &record.bankAccountNumber, &record.surname, &record.name, &record.balance) > 0) {
		WriteFile(hOut, &record, sizeof(Record), &nOut, NULL);
	}

	//Release the resources
	fclose(inputFile);
	CloseHandle(hOut);

	//Check that it has been convert properly

	hOut = CreateFile(argv[2], GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hOut == INVALID_HANDLE_VALUE) {
		_ftprintf(stderr, _T("Error when reopening the output file"));
		return 1;
	}

	DWORD nIn;
	HANDLE console;

	console = GetStdHandle(STD_OUTPUT_HANDLE);

	//Read the binary file and print it to the console
	while (ReadFile(hOut, &record, sizeof(Record), &nIn, NULL) && nIn > 0) {
		_ftprintf(stdout, _T("%i %i %s %s %i\n"), record.lineNumber, record.bankAccountNumber, record.surname, record.name, record.balance);
		if (nIn != nOut) {
			_ftprintf(stderr, _T("Error writing to console"));
			CloseHandle(hOut);
			return 1;
		}
	}

	//Wait some input to allow the user to have time to read the console
	TCHAR a;
	_ftscanf(stdin, _T("%c"), &a);

	CloseHandle(hOut);
	return 0;
}
INT _tmain(INT argc, LPTSTR argv[]) {
	if (argc < 3) {
		_ftprintf(stderr, _T("Wrong number of arguments\nUsage : %s + N directories"), argv[0]);
		return 1;
	}

	//List of the handles of the reading threads
	HANDLE* handles;
	//Handle of the comparison thread
	HANDLE comparator;
	//List of the IDs of the reading threads
	DWORD* threadsId;
	/*ID of the comparison thread and variable used to store the return value
	of some functions*/
	DWORD comparatorId, result;
	TCHAR a;

	counter = 0;
	nbThreads = argc - 1;
	//Dynamic allocation of the arrays
	handles = (HANDLE*)malloc(nbThreads * sizeof(HANDLE));
	threadsId = (DWORD*)malloc(nbThreads * sizeof(DWORD));
	entries = (LPTSTR*)malloc(nbThreads * sizeof(LPTSTR));
	argsList = (ARGS*)malloc(nbThreads * sizeof(ARGS));
	InitializeCriticalSection(&criticalSection);
	
	__try {
		//Initialization of the event blocking/releasing the readers
		eventReaders = CreateEvent(NULL, TRUE, FALSE, NULL);
		if (eventReaders == INVALID_HANDLE_VALUE) {
			_ftprintf(stderr, _T("Error when creating the event\n"));
			return 1;
		}

		//Initialization of the event blocking/releasing the comparator
		eventComparator = CreateEvent(NULL, TRUE, FALSE, NULL);
		if (eventComparator == INVALID_HANDLE_VALUE) {
			_ftprintf(stderr, _T("Error when creating the event\n"));
			//Clean-up
			CloseHandle(eventReaders);
			return 1;
		}

		//Create the comparator thread
		comparator = CreateThread(NULL, 0, compare, NULL, 0, &comparatorId);
		if (comparator == NULL) {
			_ftprintf(stderr, _T("Error %i when creating comparator thread\n"), GetLastError());
			//Clean-up
			CloseHandle(eventReaders);
			CloseHandle(eventComparator);
			return 1;
		}

		//Create the reading threads
		for (DWORD i = 0; i < nbThreads; i++) {
			argsList[i].dirName = addFinalSlash(argv[i + 1]);
			argsList[i].threadNb = i;
			handles[i] = CreateThread(NULL, 0, readingThread, &argsList[i], 0, &threadsId[i]);
			if (handles[i] == NULL) {
				_ftprintf(stderr, _T("Error %i when creating reading thread %i\n"), GetLastError(), i);
				//Clean-up
				CloseHandle(eventReaders);
				CloseHandle(eventComparator);
				TerminateThread(comparator, 2);
				CloseHandle(comparator);
				for (DWORD j = 0; j < i; j++) {
					TerminateThread(handles[i], 2);
					CloseHandle(handles[j]);
				}
				return 1;
			}
		}

		//Wait the result of the comparator thread
		WaitForSingleObject(comparator, INFINITE);
		
		//Display the result
		GetExitCodeThread(comparator, &result);
		if (result == 0) {
			_ftprintf(stdout, _T("Directories are equal\n"));
		}
		else {
			_ftprintf(stdout, _T("Directories are different\n"));
		}

		//Clean-up
		for (DWORD i = 0; i < nbThreads; i++) {
			CloseHandle(handles[i]);
		}
		CloseHandle(comparator);
		CloseHandle(eventReaders);
		CloseHandle(eventComparator);
		_ftscanf(stdin, _T("%c"), &a);
		return 0;
	}
	__finally {
		//Release the memory allocated to the dynamic arrays
		free(handles);
		free(threadsId);
		free((LPVOID)entries);
		free(argsList);
	}
}
Exemple #6
0
// Pair net. The full input is two training samples and 
// the target is set to 1 if the two examples have the same category
// else the target is 0. The second input is randomly chosen in a two setp process:
// 1) Choose  a selection radius with probability probSame if the second example will be "same"
//		or "different"
// 2) The second example is then chosen randomly from teh entire training set using the "radius"
//	selected in step (1)
HRESULT PreProcPairInputImages(PVOID pThis,
                     const  PRE_PROCESS_DATA_ARGS *pArgs,
                     LPCTSTR lpFile
                     )
{
	static float	s_probSame = 0.5;
	static int		s_sameRadius = 3;		// Note same radius is an absolute value
	static float	s_diffRadius = 1.0F;	// While Diff radius is expresed as fraction of the data set size
	static bool		s_bInputResized = false;
	static bool		s_bUseAutoEncoder = false;
	static bool		s_bDoSampleSphere = false;
	static int		s_cExtraTargetLayer = 0;
	static int		s_cExtraInput = 0;
	static int		s_cMaxRetry = 5;
	static int		s_cTupleSize = 1;
	static TCHAR	s_pairFile[MAX_PATH];
	static CDataTuple *pDataTuple = NULL;

	HRESULT hRet = S_OK;

    if (NULL != lpFile)
    {
        FILE    *fp;
        fp = _tfopen(lpFile, TEXT("r"));
        if (NULL != fp)
        {
            TCHAR   awCmd[MAX_PATH];
            TCHAR   awVal[MAX_PATH];
            float   val;
			s_pairFile[0] = TEXT('\0');
			s_bUseAutoEncoder = false;
			s_cExtraTargetLayer = 0;

			if (NULL != pDataTuple)
			{
				delete pDataTuple;
				pDataTuple = NULL;
			}

            while (2 == _ftscanf(fp, TEXT("%s %s"), awCmd, awVal))
            {
				val = (float)_tstof(awVal);
                if (0 == _tcsicmp(awCmd, TEXT("probsame")))
                {
                    s_probSame = val;
                }
                else if (0 ==  _tcsicmp(awCmd, TEXT("sameradius")))
                {
                    s_sameRadius = (int)val;
                }
                else if (0 == _tcsicmp(awCmd, TEXT("diffradius")))
                {
                    s_diffRadius = val;
                }
                else if (0 == _tcsicmp(awCmd, TEXT("maxretry")))
                {
                    s_cMaxRetry = (int)val;
                }
				else if (0 == _tcsicmp(awCmd, TEXT("pairfile")))
                {
					_tcscpy_s(s_pairFile, ARRAYSIZE(s_pairFile), awVal);
                }
                else if (0 == _tcsicmp(awCmd, TEXT("tuplesize")))
                {
                    s_cTupleSize = (int)val;
                }
                else if (0 == _tcsicmp(awCmd, TEXT("extrainput")))
                {
                    s_cExtraInput = (int)val;
                }
				else if (0 == _tcsicmp(awCmd, TEXT("autoencoder")))
                {
					s_bUseAutoEncoder = true;
                }
				else if (0 == _tcsicmp(awCmd, TEXT("numextratarget")))
                {
					s_cExtraTargetLayer = (int)val;
                }
				else if (0 == _tcsicmp(awCmd, TEXT("dosamplesphere")))
                {
					s_bDoSampleSphere = (val == 0.0F) ? false : true;
                }

            }
            fclose(fp);

            // Did everyting load
            if (    s_probSame >= 0.0F
                && s_probSame <= 1.0F 
                && s_sameRadius > 0
                && s_diffRadius > 0
                && s_diffRadius <= 1.0F
                )
            {
                hRet = S_OK;
				s_bInputResized = false;
            }
            return hRet;
        }
        return E_INVALIDARG;
    }

    NNData    *pData = (NNData *)pThis;
	PRE_PROCESS_DATA_ARGS *pIO = (PRE_PROCESS_DATA_ARGS*)pArgs;

	if (NULL == pThis || NULL == pArgs)
    {
        hRet =  E_INVALIDARG;
    }

	if (SUCCEEDED(hRet) && false == s_bInputResized)
	{
		// First time around increase the size of the buffers holding inputs and its stats
		hRet = ResizeAllInputBuffers(pData, pIO, s_cExtraInput, s_cExtraTargetLayer, s_cTupleSize);

		if (SUCCEEDED(hRet))
		{
			s_bInputResized = true;
		}
		else
		{
			return hRet;
		}
	}

	if (SUCCEEDED(hRet))
	{
		if (NULL == pDataTuple && _tcslen(s_pairFile) > 0)
		{
			pDataTuple = new CDataTuple(pData->GetNumRows(), s_cTupleSize);
			if (!SUCCEEDED(pDataTuple->LoadFromFile(s_pairFile)))
			{
				delete pDataTuple;
				pDataTuple= NULL;
			}
		}

		int		iRadius;
		int iOtherSamp = 0, iOtherSamp2 = 0;
		DREAL *pThisTarget = *(pData->GetTargetExamples() + pData->GetCurRow());
		int cRetry = 0;
		int cOtherSamp = 1;

		if (NULL == pDataTuple)
		{
			DREAL *pOtherTarget;
			if (frand() <= s_probSame)
			{
				iRadius = s_sameRadius;
				do 
				{
					iOtherSamp = PickOtherSamp(pData, iRadius);
					pOtherTarget = *(pData->GetTargetExamples() + iOtherSamp);
					++cRetry;
				} while (*pOtherTarget != *pIO->m_pTarget && cRetry < s_cMaxRetry);
			}
			else
			{
				iRadius = (int)(s_diffRadius * pData->GetNumRows() +0.5F);
				do 
				{
					iOtherSamp = PickOtherSamp(pData, iRadius);
					pOtherTarget = *(pData->GetTargetExamples() + iOtherSamp);
					++cRetry;
				} while (*pOtherTarget == *pIO->m_pTarget && cRetry < s_cMaxRetry);
			}
		}
		else
		{
			TUPLE_DATA	tuple;

			if (SUCCEEDED(pDataTuple->GetNextIdx(pData->GetCurRow(), tuple)))
			{
				int iTuple = 0;

				if (s_cTupleSize > 1)
				{
					CDataTuple::Shuffle(tuple.m_vPairs);
					iOtherSamp = tuple.m_vPairs[iTuple++];
					iOtherSamp2 = tuple.m_vPairs[iTuple++];
					cOtherSamp = 2;
				}
				else
				{
					iOtherSamp = tuple.m_vPairs[iTuple++];
				}

			}
		}

		NREAL targetDiff = 0;

		if (cOtherSamp == 1)
		{
			targetDiff = AppendOneSample(pIO, pData, pThisTarget, iOtherSamp);
		}
		else
		{
			targetDiff = AppendTwoSamples(pIO, pData, pThisTarget, iOtherSamp, iOtherSamp2);
			NREAL	*pSrc = pIO->m_pInput + 3*pIO->m_cInput;

			if (3 == s_cExtraInput)
			{
				int iSrc = 0;
				pSrc[iSrc++] = L1Distance(pIO->m_pInput, pIO->m_pInput + pIO->m_cInput, pIO->m_cInput);
				pSrc[iSrc++] = L1Distance(pIO->m_pInput, pIO->m_pInput + 2*pIO->m_cInput, pIO->m_cInput);
				pSrc[0] = __max(pSrc[0], 1.0F);
				pSrc[iSrc] = (pSrc[0] - pSrc[1]) / pSrc[0];
				pSrc[iSrc] = __max(-3.0F, pSrc[iSrc]);
				pSrc[iSrc] = __min(3.0F, pSrc[iSrc]);
				pSrc[iSrc] *= 10000;

				if (true == s_bDoSampleSphere)
				{
					pData->SphereOneSample(pThis, pIO->m_pInput, pIO->m_cInput*3+s_cExtraInput,
						pData->GetMeans(), pData->GetStdev(), pData->GetInputRange(), pData->GetInputMin());
				}
			}
		}

		if (false == s_bUseAutoEncoder)
		{
			*pIO->m_pTarget= targetDiff;
		}
		else
		{
			pIO->m_pTarget = pIO->m_pInput;
			pIO->m_cTarget = pIO->m_cInput;
			//memcpy_s(pIO->m_pTarget, pIO->m_cTarget*sizeof(*pIO->m_pTarget), pIO->m_pInput, pIO->m_cTarget*sizeof(*pIO->m_pInput));
		}

		if (pIO->cExtraTargetLayers > 0 && NULL != pIO->m_ppExtraTargetLayers)
		{
			*pIO->m_ppExtraTargetLayers[0] = targetDiff;
		}

		hRet = S_OK;
	}

	return hRet;

}
Exemple #7
0
// Treats the input data as an image. Transforms image using a random affine transformation
HRESULT PreProcImageTransform(const PVOID pThis,
                     const  PRE_PROCESS_DATA_ARGS *pArgs,
                     LPCTSTR lpFile
                     )
{
    static float    s_MaxScale = -1.0F;         // Maximum Scale
    static float    s_MaxRotation = -1.0F;      // Max Rotation
    static float    s_MaxTranslation = -1.0F;   // Max Translation
    static int      s_cCol = -1;
    static int      s_cRow = -1;
    static int      s_cImage = -1;
    static bool     s_bFileLoaded = false;
	static bool		s_bDoImageTargetTransform = false;

    HRESULT         hRet = E_FAIL;

    if (NULL != lpFile)
    {
        FILE    *fp;
        fp = _tfopen(lpFile, TEXT("r"));
        if (NULL != fp)
        {
            TCHAR   awCmd[MAX_PATH];
            float   val;

            while (2 == _ftscanf(fp, TEXT("%s %f"), awCmd, &val))
            {
                if (0 == _tcsicmp(awCmd, TEXT("rotation")))
                {
                    // Convert to radians
                    s_MaxRotation = val * (float)M_PI / 180.0F;
                }
                else if (0 ==  _tcsicmp(awCmd, TEXT("scale")))
                {
                    s_MaxScale = val;
                }
                else if (0 == _tcsicmp(awCmd, TEXT("translation")))
                {

                    s_MaxTranslation = val;
                }
                else if (0 ==  _tcsicmp(awCmd, TEXT("cols")))
                {
                    s_cCol = (int)val;
                }
                else if (0 == _tcsicmp(awCmd, TEXT("rows")))
                {
                    s_cRow = (int)val;
                }
                else if (0 == _tcsicmp(awCmd, TEXT("cImage")))
                {
                    s_cImage = (int)val;
                }
                else if (0 == _tcsicmp(awCmd, TEXT("DoTargets")))
                {
					s_bDoImageTargetTransform = (int)val == 1 ? true : false;
                }
            }
            fclose(fp);

            // Did everyting load
            if (    s_MaxRotation >= 0.0F
                && s_MaxScale >= 0.0F 
                && s_MaxTranslation >= 0.0
                && s_cCol > 0
                && s_cRow > 0
                && s_cImage > 0
                )
            {
                hRet = S_OK;
                s_bFileLoaded = true;
            }
            return hRet;
        }
        return E_INVALIDARG;
    }

    NNData    *pData = (NNData *)pThis;

    if (    true == s_bFileLoaded
        && NULL != pArgs
        && pArgs->m_cInput == s_cCol * s_cRow * s_cImage
        && NULL != pData && pData->GetEnumCount() > 1)
    {
        // Build the transform Matrix
        float   trans[2][3];
        int     iOff = s_cRow * s_cCol ;

        float   Sx = 1.0F + (fRand_s() * s_MaxScale);
        float   theta = (2.0F*fRand_s()-1.0F) * s_MaxRotation;

        trans[0][0] = Sx * cosf(theta); 
        trans[0][1] = -Sx * sinf(theta);
        trans[0][2] = s_MaxTranslation * (2.0F * fRand_s() - 1.0F);
        trans[1][0] = -trans[0][1];
        trans[1][1] = trans[0][0]; 
        trans[1][2] = s_MaxTranslation * (2.0F * fRand_s() - 1.0F);
        
        for (int iImage = 0 ; iImage < s_cImage ; ++iImage)
        {
            ImageTransform(pArgs->m_pInput + iImage*iOff, s_cCol, s_cRow, trans);
        }
		if (true == s_bDoImageTargetTransform)
		{
			trans[0][0] = cosf(theta) / Sx; 
			trans[0][1] = sinf(theta) / Sx;
			trans[0][2] /= -s_cCol;
			trans[1][0] = -trans[0][1];
			trans[1][1] = trans[0][0]; 
			trans[1][2] /= -s_cRow;
			ImageTargetTransform(pArgs->m_pTarget, pArgs->m_cTarget, trans);
		}
		hRet = S_OK;
    }

    hRet = PreProcStats(pThis, pArgs, lpFile);
    return hRet;
}
INT _tmain(INT argc, LPTSTR argv[]) {
	HANDLE threadsHandles[THREADS_NB], inputFile = NULL;
	DWORD threadsIds[THREADS_NB], nRead;

	if (argc != 2) {
		_ftprintf(stdout, _T("Wrong number of arguments\nUsage : %s inputFileName\n"), argv[0]);
		_ftscanf(stdin, _T("%c"), &a);
		return 1;
	}

	//Initialize synchronization objects
	#ifdef VERSION_A
		for (INT i = 0; i < THREADS_NB; i++)
			inputSem[i] = CreateSemaphore(NULL, 0, 1, NULL);
		outputSem = CreateSemaphore(NULL, 0, THREADS_NB, NULL);
	#endif
	#ifdef VERSION_B
		inputEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
		for (INT i = 0; i < THREADS_NB; i++)
			outputEvent[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
	#endif

	//Create the threads
	LPDWORD threadPos;
	for (INT i = 0; i < THREADS_NB; i++) {
		threadPos = (LPDWORD)malloc(sizeof(DWORD));
		*threadPos = i;
		threadsHandles[i] = CreateThread(NULL, 0, threadFunc, threadPos, 0, &threadsIds[i]);
		if (threadsHandles[i] == NULL) {
			_ftprintf(stdout, _T("Error %i when creating thread number %i\n"), GetLastError(), i);
			_ftscanf(stdin, _T("%c"), &a);
			return 1;
		}
	}

	inputFile = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (inputFile == INVALID_HANDLE_VALUE) {
		_ftprintf(stdout, _T("Error %i when opening input file\n"), GetLastError());
		_ftscanf(stdin, _T("%c"), &a);
		return 1;
	}

	/* Used to be sure that all the secondary threads have been activated and wait
	   on the event before the main thread triggers it */
	#ifdef VERSION_B
		Sleep(100);
	#endif

	//Read the file
	while (ReadFile(inputFile, (LPVOID)&inputValue, sizeof(DWORD), &nRead, NULL) && nRead > 0) {
		#ifdef VERSION_A
			for (INT i = 0; i < THREADS_NB; i++)
				ReleaseSemaphore(inputSem[i], 1, NULL);
			for (INT i = 0; i < THREADS_NB; i++) {
				WaitForSingleObject(outputSem, INFINITE);
			}
		#endif
		#ifdef VERSION_B
			PulseEvent(inputEvent);
			WaitForMultipleObjects(THREADS_NB, outputEvent, TRUE, INFINITE);
		#endif
	}

	for (INT i = 0; i < THREADS_NB; i++) {
		TerminateThread(threadsHandles[i], 0);
	}

	//Clean the synchronization objects used
	#ifdef VERSION_A
		for (INT i = 0; i < THREADS_NB; i++)
			CloseHandle(inputSem[i]);
		CloseHandle(outputSem);
	#endif
	#ifdef VERSION_B
		CloseHandle(inputEvent);
		CloseHandle(outputEvent);
	#endif

	CloseHandle(inputFile);

	//Display a special line to indicate the end of the program
	_ftprintf(stdout, _T("================================================\n"));
	_ftscanf(stdin, _T("%c"), &a);
	return 0;
}