summaryrefslogtreecommitdiff
path: root/include/fixed.h
blob: 80d3ee9ac492532873fba76e9a5033a76974d3e9 (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
#include "types.h"

#ifndef FIXED_H
#define FIXED_H

#define FIX_SHIFT 8
#define HALF_FIX_SHIFT 4
#define FIX_SCALE ( 1 << FIX_SHIFT )
#define FIX_SCALE_FLOAT ((float)(FIX_SCALE))

typedef s32 FIXED;

static inline FIXED fixed_OverMultiply(FIXED a, FIXED b) {
    // This should multiply two fixed-point numbers sacrificing a little
    // accuracy in exchange for less chance of an overflow

    return ((a >> HALF_FIX_SHIFT) * (b >> HALF_FIX_SHIFT));
}

static inline FIXED fixed_multiply (FIXED a, FIXED b) {
    // Multiply two fixed numbers. Possibility of overflow.
    return (a * b) >> FIX_SHIFT;
}

static inline FIXED fixed_divide(FIXED a, FIXED b) {
	// Divide two fixed point numbers
    if (b != 0){
        return (a * FIX_SCALE) / b;
    }
    else {
		// Return a large number if division by zero
		// Hopefully this won't break anything :P
        return 100000 << FIX_SHIFT;
    }
}

static inline FIXED float_to_fixed(float a) {
    // Convert a float to fixed point
    return ((FIXED)(a * FIX_SCALE_FLOAT));
}

static inline float fixed_to_float(FIXED a) {
    // Convert fixed point to float
    return (a / FIX_SCALE_FLOAT);
}

static inline void swapFixed(FIXED *a, FIXED *b) {
    // Swap two fixed point integer pointers
    FIXED temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

static inline FIXED fixed_sqrt(FIXED a, int iterations) {
    // Calculate square root of a fixed-point number using Binary-Search
    FIXED low = 0;
    FIXED high = a;
    FIXED mid;
    FIXED midSquared;
    for (int i = 0; i < iterations; i++) {
        mid = fixed_divide((low + high), 2 << FIX_SHIFT);
        midSquared = fixed_OverMultiply(mid, mid);
        if (midSquared == a) {
            return mid;
        }
        else if (midSquared > a) {
            high = mid;
        }
        else {
            low = mid;
        }
    }
    return mid;
}

#endif // FIXED_H