예제 #1
0
파일: main.c 프로젝트: Ghawar/libfixmath
int main(int argc, char** argv) {
    printf("libfixmath test tool\n");

    hiclock_init();

	uintptr_t args = (1 <<  8);
	uintptr_t iter = (1 <<  8);
	uintptr_t pass = (1 <<  8);

	uintptr_t i;
	srand(time(NULL));

	hiclock_t fix_duration = 0;
	hiclock_t flt_duration = 0;
	fix16_t   fix_error = 0;

	uintptr_t k;
	for(k = 0; k < pass; k++) {
		fix16_t fix_args[args];
		for(i = 0; i < args; i++)
			fix_args[i] = (rand() ^ (rand() << 16));
		fix16_t fix_result[args];
		hiclock_t fix_start = hiclock();
		for(i = 0; i < iter; i++) {
			uintptr_t j;
			for(j = 0; j < args; j++)
				fix_result[j] = fix_func(fix_args[j]);
		}
		hiclock_t fix_end = hiclock();

		float   flt_args[args];
		for(i = 0; i < args; i++)
			flt_args[i] = fix16_to_float(fix_args[i]);
		float   flt_result[args];
		hiclock_t flt_start = hiclock();
		for(i = 0; i < iter; i++) {
			uintptr_t j;
			for(j = 0; j < args; j++)
				flt_result[j] = flt_func(flt_args[j]);
		}
		hiclock_t flt_end = hiclock();

		for(i = 0; i < args; i++)
			fix_error += abs(fix16_from_float(flt_result[i]) - fix_result[i]);
		flt_duration += (flt_end - flt_start);
		fix_duration += (fix_end - fix_start);
	}

	printf("%16s: %08"PRIuHICLOCK" @ %"PRIu32"Hz\n", flt_func_str, flt_duration, HICLOCKS_PER_SEC);
	printf("%16s: %08"PRIuHICLOCK" @ %"PRIu32"Hz\n", fix_func_str, fix_duration, HICLOCKS_PER_SEC);
	printf("      Difference: %08"PRIiHICLOCK" (% 3.2f%%)\n", (flt_duration - fix_duration), ((fix_duration * 100.0) / flt_duration));
	printf("           Error: %f%%\n", ((fix16_to_dbl(fix_error) * 100.0) / (args * pass)));

    return EXIT_SUCCESS;
}
// Receive real number from serial link. The real number should be in Q16.16
// representation. This is so that the device under test doesn't have to
// do the conversion to floating-point.
static double receiveDouble(void)
{
    uint8_t buffer[4];
    int j;

    for (j = 0; j < 4; j++)
    {
        buffer[j] = receiveByte();
    }
    // The cast from uint32_t to fix16_t isn't platform-independent, because
    // the C99 specification doesn't make any guarantees about conversions
    // to signed integer types (...if the destination type cannot store the
    // source value, which will be the case if the fix16_t is negative).
    // But it should work on nearly every contemporary platform.
    return fix16_to_dbl((fix16_t)readU32LittleEndian(buffer));
}
예제 #3
0
		operator double()  const { return fix16_to_dbl(value);   }
예제 #4
0
int main()
{
    int status = 0;
    {
        COMMENT("Testing fix16_exp() corner cases");
        TEST(fix16_exp(0) == fix16_one);
        TEST(fix16_exp(fix16_minimum) == 0);
        TEST(fix16_exp(fix16_maximum) == fix16_maximum);
    }
    
    {
        COMMENT("Testing fix16_exp() accuracy over -11..4");
        
        fix16_t max_delta = -1;
        fix16_t worst = 0;
        fix16_t sum = 0;
        int count = 0;
        fix16_t a;
        
        for (a = fix16_from_dbl(-11.0); a < fix16_from_dbl(4.0); a += 31)
        {
            fix16_t result = fix16_exp(a);
            fix16_t resultf = fix16_from_dbl(exp(fix16_to_dbl(a)));
            
            fix16_t d = delta(result, resultf);
            if (d > max_delta)
            {
                max_delta = d;
                worst = a;
            }
            
            sum += d;
            count++;
        }
        
        printf("Worst delta %d with input %d\n", max_delta, worst);
        printf("Average delta %0.2f\n", (float)sum / count);
        
        TEST(max_delta < 200);
    }
    
    {
        COMMENT("Testing fix16_exp() accuracy over full range");
        
        float max_delta = -1;
        fix16_t worst = 0;
        float sum = 0;
        int count = 0;
        fix16_t a;
        
        // Test the whole range of results 0..32768 with a bit less samples
        for (a = -772243; a < 681391; a += 113)
        {
            fix16_t result = fix16_exp(a);
            fix16_t resultf = fix16_from_dbl(exp(fix16_to_dbl(a)));
            
            fix16_t d1 = delta(result, resultf);
            
            if (d1 > 0) d1--; // Forgive +-1 for the fix16_t inaccuracy
            
            float d = (float)d1 / resultf * 100;
            
            if (resultf < 1000) continue; // Percentages can explode when result is almost 0.
            
            if (d > max_delta)
            {
                max_delta = d;
                worst = a;
            }
            
            sum += d;
            count++;
        }
        
        printf("Worst delta %0.4f%% with input %d\n", max_delta, worst);
        printf("Average delta %0.4f%%\n", sum / count);
        
        TEST(max_delta < 1);
    }
    
    {
        COMMENT("Testing fix16_log() accuracy over full range");
        
        fix16_t max_delta = -1;
        fix16_t worst = 0;
        fix16_t sum = 0;
        int count = 0;
        fix16_t a;
        
        for (a = 100; a > 0 && a < fix16_maximum - 7561; a += 7561)
        {
            fix16_t result = fix16_log(a);
            fix16_t resultf = fix16_from_dbl(log(fix16_to_dbl(a)));
            
            fix16_t d = delta(result, resultf);
            if (d > max_delta)
            {
                max_delta = d;
                worst = a;
            }
            
            sum += d;
            count++;
        }
        
        printf("Worst delta %d with input %d\n", max_delta, worst);
        printf("Average delta %0.2f\n", (float)sum / count);
        
        TEST(max_delta < 20);
    }
    
    if (status != 0)
    fprintf(stdout, "\n\nSome tests FAILED!\n");

    return status;
}