| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- '''This script precalculates the correct solutions for a set of test numbers,
- and writes them to testcases.c. This is aimed for running the tests on-target,
- therefore it doesn't test all the cases or use floating point math, but
- instead generates a ~10k binary.
- The tests are chosen randomly, so there is quite good chance to eventually
- catch most errors. Because the list is not regenerated automatically, the
- functioning of the benchmark application is still deterministic and easy
- to debug.
- '''
- import math
- import random
- import struct
- # Fix16 scaling factor
- scale = 65536.
- # Fix16 overflow indicator
- overflow = -2**31
- def f16_to_float(val):
- return val / scale
- def float_to_f16(val):
- val = int(round(val * scale))
- if val >= 2**31 or val < -2**31:
- val = overflow
- return val
- def to_ui32(val):
- return struct.unpack('I', struct.pack('i', val))[0]
- testcases = [
- # Small numbers
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
- -1, -2, -3, -4, -5, -6, -7, -8, -9, -10,
-
- # Integer numbers
- 0x10000, -0x10000, 0x20000, -0x20000, 0x30000, -0x30000,
- 0x40000, -0x40000, 0x50000, -0x50000, 0x60000, -0x60000,
-
- # Fractions (1/2, 1/4, 1/8)
- 0x8000, -0x8000, 0x4000, -0x4000, 0x2000, -0x2000,
-
- # Problematic carry
- 0xFFFF, -0xFFFF, 0x1FFFF, -0x1FFFF, 0x3FFFF, -0x3FFFF,
-
- # Smallest and largest values
- 0x7FFFFFFF, -0x80000000
- ]
-
- for i in range(10):
- # Large random numbers
- testcases.append(random.randint(-0x80000000, 0x7FFFFFFF))
-
- # Small random numbers
- testcases.append(random.randint(-100000, 100000))
-
- # Tiny random numbers
- testcases.append(random.randint(-200, 200))
- out = open("testcases.c", "w")
- out.write('''
- /* Automatically generated testcases for fix16 operations
- * See generate_testcases.py for the generator.
- */
- #include <fix16.h>
- typedef struct {
- // Input
- fix16_t a;
-
- // Correct output
- fix16_t sqrt;
- fix16_t exp;
- } fix16_1op_testcase;
- typedef struct {
- // Inputs
- fix16_t a;
- fix16_t b;
-
- // Correct output
- fix16_t add;
- fix16_t sub;
- fix16_t mul;
- fix16_t div;
- } fix16_2op_testcase;
- #define TESTCASES1_COUNT (sizeof(testcases1)/sizeof(testcases1[0]))
- #define TESTCASES2_COUNT (sizeof(testcases2)/sizeof(testcases2[0]))
- ''')
- # Write testcases for 1-operand functions
- out.write('static const fix16_1op_testcase testcases1[] = {\n')
- for i in range(10):
- a = random.choice(testcases)
- if a >= 0:
- sqrt = float_to_f16(math.sqrt(f16_to_float(a)))
- else:
- sqrt = 0
-
- try:
- exp = float_to_f16(math.exp(f16_to_float(a)))
- except OverflowError:
- exp = 0x7FFFFFFF
-
- out.write(' {0x%08x, 0x%08x, 0x%08x}, // %d\n'
- % (to_ui32(a), to_ui32(sqrt), to_ui32(exp), i))
- out.write('};\n\n')
- # Write testcases for 2-operand functions
- out.write('static const fix16_2op_testcase testcases2[] = {\n')
- for i in range(50):
- a = random.choice(testcases)
- b = random.choice(testcases)
-
- add = float_to_f16(f16_to_float(a) + f16_to_float(b))
- sub = float_to_f16(f16_to_float(a) - f16_to_float(b))
- mul = float_to_f16(f16_to_float(a) * f16_to_float(b))
- if b != 0:
- div = float_to_f16(f16_to_float(a) / f16_to_float(b))
- else:
- div = 0
- out.write(' {0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x}, // %d\n'
- % (to_ui32(a), to_ui32(b), to_ui32(add), to_ui32(sub), to_ui32(mul), to_ui32(div), i))
- out.write('};\n\n')
- out.close()
-
|