aboutsummaryrefslogtreecommitdiff
path: root/Client/ThirdParty/libfixmath/benchmarks/benchmark.c
blob: 3942abc1d2c93a7637dd6f799b683aa5ffefe924 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
#ifndef NO_FLOAT
#include <math.h>
#endif

#include <fix16.h>
#include "interface.h"
#include <stdio.h>

/* Autogenerated testcases */
#include "testcases.c"

// Initializer for cyclecount_t structure.
// Max is initialized to 0 and min is 2^32-1 so that first call to cyclecount_update will set them.
#define CYCLECOUNT_INIT {0xFFFFFFFF, 0, 0, 0}

// Update cyclecount_t structure after a single measurement has been made.
static void cyclecount_update(cyclecount_t *data, uint32_t cycles)
{
    if (cycles < data->min)
        data->min = cycles;
    if (cycles > data->max)
        data->max = cycles;
    
    data->sum += cycles;
    data->count++; 
}

#define MEASURE(variable, statement) { \
    start_timing(); \
    statement; \
    cyclecount_update(&variable, end_timing()); \
}

static cyclecount_t exp_cycles = CYCLECOUNT_INIT;
static cyclecount_t sqrt_cycles = CYCLECOUNT_INIT;
static cyclecount_t add_cycles = CYCLECOUNT_INIT;
static cyclecount_t sub_cycles = CYCLECOUNT_INIT;
static cyclecount_t div_cycles = CYCLECOUNT_INIT;
static cyclecount_t mul_cycles = CYCLECOUNT_INIT;

static cyclecount_t float_sqrtf_cycles = CYCLECOUNT_INIT;
static cyclecount_t float_expf_cycles = CYCLECOUNT_INIT;
static cyclecount_t float_add_cycles = CYCLECOUNT_INIT;
static cyclecount_t float_sub_cycles = CYCLECOUNT_INIT;
static cyclecount_t float_div_cycles = CYCLECOUNT_INIT;
static cyclecount_t float_mul_cycles = CYCLECOUNT_INIT;

static fix16_t delta(fix16_t result, fix16_t expected)
{
#ifdef FIXMATH_NO_OVERFLOW
    // Ignore overflow errors when the detection is turned off
    if (expected == fix16_minimum)
        return 0;
#endif

    if (result >= expected)
    {
        return result - expected;
    }
    else
    {
        return expected - result;
    }
}

#ifdef FIXMATH_NO_ROUNDING
const fix16_t max_delta = 1;
#else
const fix16_t max_delta = 0;
#endif

int main()
{
    int i;
    interface_init();
    
    start_timing();
    print_value("Timestamp bias", end_timing());
    
    for (i = 0; i < TESTCASES1_COUNT; i++)
    {
        fix16_t input = testcases1[i].a;
        fix16_t result;
        fix16_t expected = testcases1[i].sqrt;
        MEASURE(sqrt_cycles, result = fix16_sqrt(input));
        
        if (input > 0 && delta(result, expected) > max_delta)
        {
            print_value("Failed SQRT, i", i);
            print_value("Failed SQRT, input", input);
            print_value("Failed SQRT, output", result);
            print_value("Failed SQRT, expected", expected);
        }
        
        expected = testcases1[i].exp;
        MEASURE(exp_cycles, result = fix16_exp(input));
        
        if (delta(result, expected) > 400)
        {
            print_value("Failed EXP, i", i);
            print_value("Failed EXP, input", input);
            print_value("Failed EXP, output", result);
            print_value("Failed EXP, expected", expected);
        }
    }

    for (i = 0; i < TESTCASES2_COUNT; i++)
    {
        fix16_t a = testcases2[i].a;
        fix16_t b = testcases2[i].b;
        volatile fix16_t result;
        
        fix16_t expected = testcases2[i].add;
        MEASURE(add_cycles, result = fix16_add(a, b));
        if (delta(result, expected) > max_delta)
        {
            print_value("Failed ADD, i", i);
            print_value("Failed ADD, a", a);
            print_value("Failed ADD, b", b);
            print_value("Failed ADD, output", result);
            print_value("Failed ADD, expected", expected);
        }
        
        expected = testcases2[i].sub;
        MEASURE(sub_cycles, result = fix16_sub(a, b));
        if (delta(result, expected) > max_delta)
        {
            print_value("Failed SUB, i", i);
            print_value("Failed SUB, a", a);
            print_value("Failed SUB, b", b);
            print_value("Failed SUB, output", result);
            print_value("Failed SUB, expected", expected);
        }
        
        expected = testcases2[i].mul;
        MEASURE(mul_cycles, result = fix16_mul(a, b));
        if (delta(result, expected) > max_delta)
        {
            print_value("Failed MUL, i", i);
            print_value("Failed MUL, a", a);
            print_value("Failed MUL, b", b);
            print_value("Failed MUL, output", result);
            print_value("Failed MUL, expected", expected);
        }
        
        if (b != 0)
        {
            expected = testcases2[i].div;
            MEASURE(div_cycles, result = fix16_div(a, b));
            if (delta(result, expected) > max_delta)
            {
                print_value("Failed DIV, i", i);
                print_value("Failed DIV, a", a);
                print_value("Failed DIV, b", b);
                print_value("Failed DIV, output", result);
                print_value("Failed DIV, expected", expected);
            }
        }
    }
    
    /* Compare with floating point performance */
#ifndef NO_FLOAT
    for (i = 0; i < TESTCASES1_COUNT; i++)
    {
        float input = fix16_to_float(testcases1[i].a);
        volatile float result;
        MEASURE(float_sqrtf_cycles, result = sqrtf(input));
        MEASURE(float_expf_cycles, result = expf(input));
    }
    
    for (i = 0; i < TESTCASES2_COUNT; i++)
    {
        float a = fix16_to_float(testcases2[i].a);
        float b = fix16_to_float(testcases2[i].b);
        volatile float result;
        MEASURE(float_add_cycles, result = a + b);
        MEASURE(float_sub_cycles, result = a - b);
        MEASURE(float_mul_cycles, result = a * b);
        
        if (b != 0)
        {
            MEASURE(float_div_cycles, result = a / b);
        }
    }
#endif 

    print("fix16_sqrt", &sqrt_cycles);
    print("float sqrtf", &float_sqrtf_cycles);
    print("fix16_exp", &exp_cycles);
    print("float expf", &float_expf_cycles);
    print("fix16_add", &add_cycles);
    print("float add", &float_add_cycles);
    print("fix16_sub", &sub_cycles);
    print("float sub", &float_sub_cycles);
    print("fix16_mul", &mul_cycles);
    print("float mul", &float_mul_cycles);
    print("fix16_div", &div_cycles);
    print("float div", &float_div_cycles);

    return 0;
}