/* 
 * Small script to test whether or not multiplying an integer with a
 * floating point number and back changes the integer
 */

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

main(){
   
    // Variables to count the iterations. Loop over all integers from
    // i to max_i.
    int i = 0;
    int max_i = 200000;

    // How many floats should be tested per integer.
    int number_of_floats = 100000;
    // The range of the floating point numbers.
    float min_float = 0.00001;
    float max_float = 100000.0;
    float range = max_float - min_float;
    // Once again because small numbers might cause more problems.
    float small_min_float = 0.00001;
    float small_max_float = 1.0;
    float small_range = small_max_float - small_min_float;

    // Keep count.
    long absolute_error_count = 0;
    long absolute_sample_count = 0;

    // Generate a random number seed based on the time to get different results every time.
    srand(time(NULL));

    // Loop over all integer values.
    while (i<max_i){

	// Only print all 1000 values.
	if (i%1000 == 0){
		printf("Current Integer: %i of %i\n", i, max_i);
	}

	int current_errors = 0;
	int current_count = 0;

	// Loop over random floating point values for every integer.
	int j = 1;
	while (j < number_of_floats){
		// Get the random float normalized between 0 and 1 and scale
		// accordingly.
		float random_float = (float)rand()/(float)RAND_MAX;
		random_float = min_float + random_float * range;
		// Convert integer to floating point.
		float float_i = i * random_float;
		float_i /= random_float;
		// Round to avoid errors.
		float_i = round(float_i);
		// Convert back to integers.
		int int_i = (int) float_i;
		// Check if anything changed.
		if (int_i != i){
			absolute_error_count += 1;
		}

		// Again for the very small numbers.
		random_float = (float)rand()/(float)RAND_MAX;
		random_float = small_min_float + random_float * small_range;
		// Convert integer to floating point.
		float_i = i * random_float;
		float_i /= random_float;
		// Round to avoid errors.
		float_i = round(float_i);
		// Convert back to integers.
		int_i = (int) float_i;
		// Check if anything changed.
		if (int_i != i){
			absolute_error_count += 1;
		}
    		absolute_sample_count += 2;

		// Increment.
		j += 1;
	}

        i += 1;
    }
    double relative = ((double) absolute_error_count) / ((double) absolute_sample_count);
    printf("\n\n===============\nFinal result:\n\tSamples: %li\nErrors: %li (%.3f %%)\n\n", absolute_sample_count, absolute_error_count, relative);
}



